Skip to content

Commit

Permalink
fix(nodejs): merge Indirect, Dev, ExternalReferences fields for…
Browse files Browse the repository at this point in the history
… same deps from `package-lock.json` files v2 or later (aquasecurity#6356)

Signed-off-by: knqyf263 <[email protected]>
Co-authored-by: knqyf263 <[email protected]>
  • Loading branch information
DmitriyLewen and knqyf263 authored Mar 27, 2024
1 parent ade033a commit 258d153
Show file tree
Hide file tree
Showing 5 changed files with 202 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgw
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
Expand Down
48 changes: 36 additions & 12 deletions pkg/dependency/parser/nodejs/npm/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"io"
"path"
"slices"
"sort"
"strings"

Expand Down Expand Up @@ -115,28 +116,42 @@ func (p *Parser) parseV2(packages map[string]Package) ([]types.Library, []types.
EndLine: pkg.EndLine,
}

var ref types.ExternalRef
if pkg.Resolved != "" {
ref = types.ExternalRef{
Type: types.RefOther,
URL: pkg.Resolved,
}
}

pkgIndirect := isIndirectLib(pkgPath, directDeps)

// There are cases when similar libraries use same dependencies
// we need to add location for each these dependencies
if savedLib, ok := libs[pkgID]; ok {
savedLib.Dev = savedLib.Dev && pkg.Dev
savedLib.Indirect = savedLib.Indirect && pkgIndirect

if ref.URL != "" && !slices.Contains(savedLib.ExternalReferences, ref) {
savedLib.ExternalReferences = append(savedLib.ExternalReferences, ref)
sortExternalReferences(savedLib.ExternalReferences)
}

savedLib.Locations = append(savedLib.Locations, location)
sort.Sort(savedLib.Locations)

libs[pkgID] = savedLib
continue
}

lib := types.Library{
ID: pkgID,
Name: pkgName,
Version: pkg.Version,
Indirect: isIndirectLib(pkgPath, directDeps),
Dev: pkg.Dev,
ExternalReferences: []types.ExternalRef{
{
Type: types.RefOther,
URL: pkg.Resolved,
},
},
Locations: []types.Location{location},
ID: pkgID,
Name: pkgName,
Version: pkg.Version,
Indirect: pkgIndirect,
Dev: pkg.Dev,
ExternalReferences: lo.Ternary(ref.URL != "", []types.ExternalRef{ref}, nil),
Locations: []types.Location{location},
}
libs[pkgID] = lib

Expand Down Expand Up @@ -385,3 +400,12 @@ func (t *Package) UnmarshalJSONWithMetadata(node jfather.Node) error {
func packageID(name, version string) string {
return dependency.ID(ftypes.Npm, name, version)
}

func sortExternalReferences(refs []types.ExternalRef) {
sort.Slice(refs, func(i, j int) bool {
if refs[i].Type != refs[j].Type {
return refs[i].Type < refs[j].Type
}
return refs[i].URL < refs[j].URL
})
}
6 changes: 6 additions & 0 deletions pkg/dependency/parser/nodejs/npm/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ func TestParse(t *testing.T) {
want: npmV3WithWorkspaceLibs,
wantDeps: npmV3WithWorkspaceDeps,
},
{
name: "lock file v3 contains same dev and non-dev dependencies",
file: "testdata/package-lock_v3_with-same-dev-and-non-dev.json",
want: npmV3WithSameDevAndNonDevLibs,
wantDeps: npmV3WithSameDevAndNonDevDeps,
},
{
name: "lock version v3 with workspace and without direct deps field",
file: "testdata/package-lock_v3_without_root_deps_field.json",
Expand Down
85 changes: 85 additions & 0 deletions pkg/dependency/parser/nodejs/npm/parse_testcase.go
Original file line number Diff line number Diff line change
Expand Up @@ -1516,4 +1516,89 @@ var (
DependsOn: []string{"[email protected]"},
},
}

npmV3WithSameDevAndNonDevLibs = []types.Library{
{
ID: "[email protected]",
Name: "fsevents",
Version: "1.2.9",
Dev: true,
ExternalReferences: []types.ExternalRef{
{
Type: types.RefOther,
URL: "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz",
},
},
Locations: []types.Location{
{
StartLine: 18,
EndLine: 37,
},
},
},
{
ID: "[email protected]",
Name: "minimist",
Version: "0.0.8",
Indirect: false,
Dev: false,
ExternalReferences: []types.ExternalRef{
{
Type: types.RefOther,
URL: "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
},
},
Locations: []types.Location{
{
StartLine: 38,
EndLine: 43,
},
{
StartLine: 68,
EndLine: 72,
},
},
},
{
ID: "[email protected]",
Name: "mkdirp",
Version: "0.5.1",
Indirect: true,
Dev: true,
Locations: []types.Location{
{
StartLine: 44,
EndLine: 55,
},
},
},
{
ID: "[email protected]",
Name: "node-pre-gyp",
Version: "0.12.0",
Indirect: true,
Dev: true,
Locations: []types.Location{
{
StartLine: 56,
EndLine: 67,
},
},
},
}

npmV3WithSameDevAndNonDevDeps = []types.Dependency{
{
ID: "[email protected]",
DependsOn: []string{"[email protected]"},
},
{
ID: "[email protected]",
DependsOn: []string{"[email protected]"},
},
{
ID: "[email protected]",
DependsOn: []string{"[email protected]"},
},
}
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
{
"name": "5139",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "5139",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"minimist": "^0.0.8"
},
"devDependencies": {
"fsevents": "^1.2.9"
}
},
"node_modules/fsevents": {
"version": "1.2.9",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz",
"integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==",
"bundleDependencies": [
"node-pre-gyp"
],
"deprecated": "The v1 package contains DANGEROUS / INSECURE binaries. Upgrade to safe fsevents v2",
"dev": true,
"hasInstallScript": true,
"os": [
"darwin"
],
"dependencies": {
"node-pre-gyp": "^0.12.0"
},
"engines": {
"node": ">=4.0"
}
},
"node_modules/fsevents/node_modules/minimist": {
"version": "0.0.8",
"dev": true,
"inBundle": true,
"license": "MIT"
},
"node_modules/fsevents/node_modules/mkdirp": {
"version": "0.5.1",
"dev": true,
"inBundle": true,
"license": "MIT",
"dependencies": {
"minimist": "0.0.8"
},
"bin": {
"mkdirp": "bin/cmd.js"
}
},
"node_modules/fsevents/node_modules/node-pre-gyp": {
"version": "0.12.0",
"dev": true,
"inBundle": true,
"license": "BSD-3-Clause",
"dependencies": {
"mkdirp": "^0.5.1"
},
"bin": {
"node-pre-gyp": "bin/node-pre-gyp"
}
},
"node_modules/minimist": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha512-miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q=="
}
}
}

0 comments on commit 258d153

Please sign in to comment.