mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-22 23:26:39 -08:00
feat(nodejs): add dependency line numbers for npm lock files (#2932)
This commit is contained in:
2
go.mod
2
go.mod
@@ -9,7 +9,7 @@ require (
|
||||
github.com/alicebob/miniredis/v2 v2.23.0
|
||||
github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986
|
||||
github.com/aquasecurity/defsec v0.78.0
|
||||
github.com/aquasecurity/go-dep-parser v0.0.0-20221003104638-a5451f447820
|
||||
github.com/aquasecurity/go-dep-parser v0.0.0-20221011183558-5415cc446853
|
||||
github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce
|
||||
github.com/aquasecurity/go-npm-version v0.0.0-20201110091526-0b796d180798
|
||||
github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46
|
||||
|
||||
4
go.sum
4
go.sum
@@ -197,8 +197,8 @@ github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986 h1:2a30
|
||||
github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986/go.mod h1:NT+jyeCzXk6vXR5MTkdn4z64TgGfE5HMLC8qfj5unl8=
|
||||
github.com/aquasecurity/defsec v0.78.0 h1:C0HjNrKtEM2LT1+adIV5rwczBobqnaJtbZx8D7AgMDQ=
|
||||
github.com/aquasecurity/defsec v0.78.0/go.mod h1:wg9tVostHI0ynguaVfw+CDxrsQM/nY0sJIRmpu9FzhU=
|
||||
github.com/aquasecurity/go-dep-parser v0.0.0-20221003104638-a5451f447820 h1:Rz33hTHMlsXx1H/Fyk6GdJbF0GGIPTequSrvs8ujkMk=
|
||||
github.com/aquasecurity/go-dep-parser v0.0.0-20221003104638-a5451f447820/go.mod h1:6G1Y5nht5TL9kr1SzmrdE8PrmbNXo9nHx3qFR3qURg0=
|
||||
github.com/aquasecurity/go-dep-parser v0.0.0-20221011183558-5415cc446853 h1:Ll9CkzGrZgVXvDARqv2N0R90kAWRwmJEKmg2D4M7v/0=
|
||||
github.com/aquasecurity/go-dep-parser v0.0.0-20221011183558-5415cc446853/go.mod h1:n1NDYrNV4RFozrMCpS8ur2Y8pVTnh9rbOoBr3F9DF0A=
|
||||
github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce h1:QgBRgJvtEOBtUXilDb1MLi1p1MWoyFDXAu5DEUl5nwM=
|
||||
github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce/go.mod h1:HXgVzOPvXhVGLJs4ZKO817idqr/xhwsTcj17CLYY74s=
|
||||
github.com/aquasecurity/go-mock-aws v0.0.0-20220726154943-99847deb62b0 h1:tihCUjLWkF0b1SAjAKcFltUs3SpsqGrLtI+Frye0D10=
|
||||
|
||||
@@ -65,6 +65,7 @@ func TestFilesystem(t *testing.T) {
|
||||
args: args{
|
||||
securityChecks: "vuln",
|
||||
input: "testdata/fixtures/fs/nodejs",
|
||||
listAllPkgs: true,
|
||||
},
|
||||
golden: "testdata/nodejs.json.golden",
|
||||
},
|
||||
|
||||
196
integration/testdata/nodejs.json.golden
vendored
196
integration/testdata/nodejs.json.golden
vendored
@@ -19,6 +19,202 @@
|
||||
"Target": "package-lock.json",
|
||||
"Class": "lang-pkgs",
|
||||
"Type": "npm",
|
||||
"Packages": [
|
||||
{
|
||||
"ID": "asap@2.0.6",
|
||||
"Name": "asap",
|
||||
"Version": "2.0.6",
|
||||
"Indirect": true,
|
||||
"Layer": {},
|
||||
"Locations": [
|
||||
{
|
||||
"StartLine": 6,
|
||||
"EndLine": 10
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "jquery@3.3.9",
|
||||
"Name": "jquery",
|
||||
"Version": "3.3.9",
|
||||
"Indirect": true,
|
||||
"Layer": {},
|
||||
"Locations": [
|
||||
{
|
||||
"StartLine": 16,
|
||||
"EndLine": 20
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "js-tokens@4.0.0",
|
||||
"Name": "js-tokens",
|
||||
"Version": "4.0.0",
|
||||
"Indirect": true,
|
||||
"Layer": {},
|
||||
"Locations": [
|
||||
{
|
||||
"StartLine": 21,
|
||||
"EndLine": 25
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "lodash@4.17.4",
|
||||
"Name": "lodash",
|
||||
"Version": "4.17.4",
|
||||
"Indirect": true,
|
||||
"Layer": {},
|
||||
"Locations": [
|
||||
{
|
||||
"StartLine": 11,
|
||||
"EndLine": 15
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "loose-envify@1.4.0",
|
||||
"Name": "loose-envify",
|
||||
"Version": "1.4.0",
|
||||
"Indirect": true,
|
||||
"DependsOn": [
|
||||
"js-tokens@4.0.0"
|
||||
],
|
||||
"Layer": {},
|
||||
"Locations": [
|
||||
{
|
||||
"StartLine": 26,
|
||||
"EndLine": 33
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "object-assign@4.1.1",
|
||||
"Name": "object-assign",
|
||||
"Version": "4.1.1",
|
||||
"Indirect": true,
|
||||
"Layer": {},
|
||||
"Locations": [
|
||||
{
|
||||
"StartLine": 34,
|
||||
"EndLine": 38
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "promise@8.0.3",
|
||||
"Name": "promise",
|
||||
"Version": "8.0.3",
|
||||
"Indirect": true,
|
||||
"DependsOn": [
|
||||
"asap@2.0.6"
|
||||
],
|
||||
"Layer": {},
|
||||
"Locations": [
|
||||
{
|
||||
"StartLine": 39,
|
||||
"EndLine": 46
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "prop-types@15.7.2",
|
||||
"Name": "prop-types",
|
||||
"Version": "15.7.2",
|
||||
"Indirect": true,
|
||||
"DependsOn": [
|
||||
"loose-envify@1.4.0",
|
||||
"object-assign@4.1.1",
|
||||
"react-is@16.8.6"
|
||||
],
|
||||
"Layer": {},
|
||||
"Locations": [
|
||||
{
|
||||
"StartLine": 47,
|
||||
"EndLine": 56
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "react@16.8.6",
|
||||
"Name": "react",
|
||||
"Version": "16.8.6",
|
||||
"Indirect": true,
|
||||
"DependsOn": [
|
||||
"loose-envify@1.4.0",
|
||||
"object-assign@4.1.1",
|
||||
"prop-types@15.7.2",
|
||||
"scheduler@0.13.6"
|
||||
],
|
||||
"Layer": {},
|
||||
"Locations": [
|
||||
{
|
||||
"StartLine": 57,
|
||||
"EndLine": 67
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "react-is@16.8.6",
|
||||
"Name": "react-is",
|
||||
"Version": "16.8.6",
|
||||
"Indirect": true,
|
||||
"Layer": {},
|
||||
"Locations": [
|
||||
{
|
||||
"StartLine": 68,
|
||||
"EndLine": 72
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "redux@4.0.1",
|
||||
"Name": "redux",
|
||||
"Version": "4.0.1",
|
||||
"Indirect": true,
|
||||
"DependsOn": [
|
||||
"loose-envify@1.4.0",
|
||||
"symbol-observable@1.2.0"
|
||||
],
|
||||
"Layer": {},
|
||||
"Locations": [
|
||||
{
|
||||
"StartLine": 73,
|
||||
"EndLine": 81
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "scheduler@0.13.6",
|
||||
"Name": "scheduler",
|
||||
"Version": "0.13.6",
|
||||
"Indirect": true,
|
||||
"DependsOn": [
|
||||
"loose-envify@1.4.0",
|
||||
"object-assign@4.1.1"
|
||||
],
|
||||
"Layer": {},
|
||||
"Locations": [
|
||||
{
|
||||
"StartLine": 82,
|
||||
"EndLine": 90
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "symbol-observable@1.2.0",
|
||||
"Name": "symbol-observable",
|
||||
"Version": "1.2.0",
|
||||
"Indirect": true,
|
||||
"Layer": {},
|
||||
"Locations": [
|
||||
{
|
||||
"StartLine": 91,
|
||||
"EndLine": 95
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"Vulnerabilities": [
|
||||
{
|
||||
"VulnerabilityID": "CVE-2019-11358",
|
||||
|
||||
@@ -42,6 +42,14 @@ func ToAnalysisResult(fileType, filePath, libFilePath string, libs []godeptypes.
|
||||
licenses[i] = licensing.Normalize(strings.TrimSpace(license))
|
||||
}
|
||||
}
|
||||
var locs []types.Location
|
||||
for _, loc := range lib.Locations {
|
||||
l := types.Location{
|
||||
StartLine: loc.StartLine,
|
||||
EndLine: loc.EndLine,
|
||||
}
|
||||
locs = append(locs, l)
|
||||
}
|
||||
pkgs = append(pkgs, types.Package{
|
||||
ID: lib.ID,
|
||||
Name: lib.Name,
|
||||
@@ -50,6 +58,7 @@ func ToAnalysisResult(fileType, filePath, libFilePath string, libs []godeptypes.
|
||||
Indirect: lib.Indirect,
|
||||
Licenses: licenses,
|
||||
DependsOn: deps[lib.ID],
|
||||
Locations: locs,
|
||||
})
|
||||
}
|
||||
apps := []types.Application{{
|
||||
|
||||
@@ -28,7 +28,7 @@ func (a npmLibraryAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisIn
|
||||
p := npm.NewParser()
|
||||
res, err := language.Analyze(types.Npm, input.FilePath, input.Content, p)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("unable to parse package-lock.json: %w", err)
|
||||
return nil, xerrors.Errorf("unable to parse %s: %w", input.FilePath, err)
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
194
pkg/fanal/analyzer/language/nodejs/npm/npm_test.go
Normal file
194
pkg/fanal/analyzer/language/nodejs/npm/npm_test.go
Normal file
@@ -0,0 +1,194 @@
|
||||
package npm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/analyzer"
|
||||
"github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_npmLibraryAnalyzer_Analyze(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
inputFile string
|
||||
want *analyzer.AnalysisResult
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
inputFile: "testdata/package-lock.json",
|
||||
want: &analyzer.AnalysisResult{
|
||||
Applications: []types.Application{
|
||||
{
|
||||
Type: types.Npm,
|
||||
FilePath: "testdata/package-lock.json",
|
||||
Libraries: []types.Package{
|
||||
{
|
||||
ID: "array-flatten@1.1.1",
|
||||
Name: "array-flatten",
|
||||
Version: "1.1.1",
|
||||
Indirect: true,
|
||||
Locations: []types.Location{
|
||||
{
|
||||
StartLine: 12,
|
||||
EndLine: 16,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "body-parser@1.18.3",
|
||||
Name: "body-parser",
|
||||
Version: "1.18.3",
|
||||
Indirect: true,
|
||||
DependsOn: []string{"debug@2.6.9"},
|
||||
Locations: []types.Location{
|
||||
{
|
||||
StartLine: 17,
|
||||
EndLine: 39,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "debug@2.6.9",
|
||||
Name: "debug",
|
||||
Version: "2.6.9",
|
||||
Indirect: true,
|
||||
DependsOn: []string{"ms@2.0.0"},
|
||||
Locations: []types.Location{
|
||||
{
|
||||
StartLine: 25,
|
||||
EndLine: 32,
|
||||
},
|
||||
{
|
||||
StartLine: 48,
|
||||
EndLine: 55,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "express@4.16.4",
|
||||
Name: "express",
|
||||
Version: "4.16.4",
|
||||
Indirect: true,
|
||||
DependsOn: []string{"debug@2.6.9"},
|
||||
Locations: []types.Location{
|
||||
{
|
||||
StartLine: 40,
|
||||
EndLine: 62,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "ms@2.0.0",
|
||||
Name: "ms",
|
||||
Version: "2.0.0",
|
||||
Indirect: true,
|
||||
Locations: []types.Location{
|
||||
{
|
||||
StartLine: 33,
|
||||
EndLine: 37,
|
||||
},
|
||||
{
|
||||
StartLine: 56,
|
||||
EndLine: 60,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "ms@2.1.1",
|
||||
Name: "ms",
|
||||
Version: "2.1.1",
|
||||
Indirect: true,
|
||||
Locations: []types.Location{
|
||||
{
|
||||
StartLine: 63,
|
||||
EndLine: 67,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "sad path",
|
||||
inputFile: "testdata/wrong.json",
|
||||
wantErr: "unable to parse testdata/wrong.json",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
f, err := os.Open(tt.inputFile)
|
||||
require.NoError(t, err)
|
||||
defer f.Close()
|
||||
|
||||
a := npmLibraryAnalyzer{}
|
||||
got, err := a.Analyze(context.Background(), analyzer.AnalysisInput{
|
||||
FilePath: tt.inputFile,
|
||||
Content: f,
|
||||
})
|
||||
|
||||
if tt.wantErr != "" {
|
||||
require.NotNil(t, err)
|
||||
assert.Contains(t, err.Error(), tt.wantErr)
|
||||
return
|
||||
}
|
||||
|
||||
assert.NoError(t, err)
|
||||
sortPkgs(got.Applications[0].Libraries)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func sortPkgs(libs []types.Package) {
|
||||
sort.Slice(libs, func(i, j int) bool {
|
||||
ret := strings.Compare(libs[i].Name, libs[j].Name)
|
||||
if ret == 0 {
|
||||
return libs[i].Version < libs[j].Version
|
||||
}
|
||||
return ret < 0
|
||||
})
|
||||
for _, lib := range libs {
|
||||
sortLocations(lib.Locations)
|
||||
}
|
||||
}
|
||||
|
||||
func sortLocations(locs []types.Location) {
|
||||
sort.Slice(locs, func(i, j int) bool {
|
||||
return locs[i].StartLine < locs[j].StartLine
|
||||
})
|
||||
}
|
||||
|
||||
func Test_nodePkgLibraryAnalyzer_Required(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
filePath string
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
filePath: "npm/package-lock.json",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "sad path",
|
||||
filePath: "npm/package.json",
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
a := npmLibraryAnalyzer{}
|
||||
got := a.Required(tt.filePath, nil)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
69
pkg/fanal/analyzer/language/nodejs/npm/testdata/package-lock.json
generated
vendored
Normal file
69
pkg/fanal/analyzer/language/nodejs/npm/testdata/package-lock.json
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"ansi-colors": {
|
||||
"version": "3.2.3",
|
||||
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz",
|
||||
"integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==",
|
||||
"dev": true
|
||||
},
|
||||
"array-flatten": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
|
||||
},
|
||||
"body-parser": {
|
||||
"version": "1.18.3",
|
||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz",
|
||||
"integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=",
|
||||
"requires": {
|
||||
"debug": "2.6.9"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
}
|
||||
}
|
||||
},
|
||||
"express": {
|
||||
"version": "4.16.4",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz",
|
||||
"integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==",
|
||||
"requires": {
|
||||
"debug": "2.6.9"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
}
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
|
||||
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
|
||||
}
|
||||
}
|
||||
}
|
||||
1
pkg/fanal/analyzer/language/nodejs/npm/testdata/wrong.json
vendored
Normal file
1
pkg/fanal/analyzer/language/nodejs/npm/testdata/wrong.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{broken}
|
||||
@@ -736,28 +736,52 @@
|
||||
"Name": "asap",
|
||||
"Version": "2.0.6",
|
||||
"Indirect": true,
|
||||
"Layer": {}
|
||||
"Layer": {},
|
||||
"Locations": [
|
||||
{
|
||||
"StartLine": 6,
|
||||
"EndLine": 10
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "jquery@3.3.9",
|
||||
"Name": "jquery",
|
||||
"Version": "3.3.9",
|
||||
"Indirect": true,
|
||||
"Layer": {}
|
||||
"Layer": {},
|
||||
"Locations": [
|
||||
{
|
||||
"StartLine": 16,
|
||||
"EndLine": 20
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "js-tokens@4.0.0",
|
||||
"Name": "js-tokens",
|
||||
"Version": "4.0.0",
|
||||
"Indirect": true,
|
||||
"Layer": {}
|
||||
"Layer": {},
|
||||
"Locations": [
|
||||
{
|
||||
"StartLine": 21,
|
||||
"EndLine": 25
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "lodash@4.17.4",
|
||||
"Name": "lodash",
|
||||
"Version": "4.17.4",
|
||||
"Indirect": true,
|
||||
"Layer": {}
|
||||
"Layer": {},
|
||||
"Locations": [
|
||||
{
|
||||
"StartLine": 11,
|
||||
"EndLine": 15
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "loose-envify@1.4.0",
|
||||
@@ -765,6 +789,12 @@
|
||||
"Version": "1.4.0",
|
||||
"Indirect": true,
|
||||
"Layer": {},
|
||||
"Locations": [
|
||||
{
|
||||
"StartLine": 26,
|
||||
"EndLine": 33
|
||||
}
|
||||
],
|
||||
"DependsOn": ["js-tokens@4.0.0"]
|
||||
},
|
||||
{
|
||||
@@ -772,7 +802,13 @@
|
||||
"Name": "object-assign",
|
||||
"Version": "4.1.1",
|
||||
"Indirect": true,
|
||||
"Layer": {}
|
||||
"Layer": {},
|
||||
"Locations": [
|
||||
{
|
||||
"StartLine": 34,
|
||||
"EndLine": 38
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "promise@8.0.3",
|
||||
@@ -780,6 +816,12 @@
|
||||
"Version": "8.0.3",
|
||||
"Indirect": true,
|
||||
"Layer": {},
|
||||
"Locations": [
|
||||
{
|
||||
"StartLine": 39,
|
||||
"EndLine": 46
|
||||
}
|
||||
],
|
||||
"DependsOn": ["asap@2.0.6"]
|
||||
},
|
||||
{
|
||||
@@ -788,6 +830,12 @@
|
||||
"Version": "15.7.2",
|
||||
"Indirect": true,
|
||||
"Layer": {},
|
||||
"Locations": [
|
||||
{
|
||||
"StartLine": 47,
|
||||
"EndLine": 56
|
||||
}
|
||||
],
|
||||
"DependsOn": ["loose-envify@1.4.0", "object-assign@4.1.1", "react-is@16.8.6"]
|
||||
},
|
||||
{
|
||||
@@ -796,6 +844,12 @@
|
||||
"Version": "16.8.6",
|
||||
"Indirect": true,
|
||||
"Layer": {},
|
||||
"Locations": [
|
||||
{
|
||||
"StartLine": 57,
|
||||
"EndLine": 67
|
||||
}
|
||||
],
|
||||
"DependsOn": ["loose-envify@1.4.0", "object-assign@4.1.1", "prop-types@15.7.2", "scheduler@0.13.6"]
|
||||
},
|
||||
{
|
||||
@@ -803,6 +857,12 @@
|
||||
"Name": "react-is",
|
||||
"Version": "16.8.6",
|
||||
"Indirect": true,
|
||||
"Locations": [
|
||||
{
|
||||
"StartLine": 68,
|
||||
"EndLine": 72
|
||||
}
|
||||
],
|
||||
"Layer": {}
|
||||
},
|
||||
{
|
||||
@@ -811,6 +871,12 @@
|
||||
"Version": "4.0.1",
|
||||
"Indirect": true,
|
||||
"Layer": {},
|
||||
"Locations": [
|
||||
{
|
||||
"StartLine": 73,
|
||||
"EndLine": 81
|
||||
}
|
||||
],
|
||||
"DependsOn": ["loose-envify@1.4.0", "symbol-observable@1.2.0"]
|
||||
},
|
||||
{
|
||||
@@ -819,6 +885,12 @@
|
||||
"Version": "0.13.6",
|
||||
"Indirect": true,
|
||||
"Layer": {},
|
||||
"Locations": [
|
||||
{
|
||||
"StartLine": 82,
|
||||
"EndLine": 90
|
||||
}
|
||||
],
|
||||
"DependsOn": ["loose-envify@1.4.0", "object-assign@4.1.1"]
|
||||
},
|
||||
{
|
||||
@@ -826,7 +898,13 @@
|
||||
"Name": "symbol-observable",
|
||||
"Version": "1.2.0",
|
||||
"Indirect": true,
|
||||
"Layer": {}
|
||||
"Layer": {},
|
||||
"Locations": [
|
||||
{
|
||||
"StartLine": 91,
|
||||
"EndLine": 95
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -47,6 +47,14 @@ type Package struct {
|
||||
|
||||
// Each package metadata have the file path, while the package from lock files does not have.
|
||||
FilePath string `json:",omitempty"`
|
||||
|
||||
// lines from the lock file where the dependency is written
|
||||
Locations []Location `json:",omitempty"`
|
||||
}
|
||||
|
||||
type Location struct {
|
||||
StartLine int `json:",omitempty"`
|
||||
EndLine int `json:",omitempty"`
|
||||
}
|
||||
|
||||
// BuildInfo represents information under /root/buildinfo in RHEL
|
||||
|
||||
Reference in New Issue
Block a user