diff --git a/pkg/commands/artifact/run.go b/pkg/commands/artifact/run.go index fa454c0cd276..b85cd0c70a64 100644 --- a/pkg/commands/artifact/run.go +++ b/pkg/commands/artifact/run.go @@ -563,6 +563,7 @@ func (r *runner) initScannerConfig(opts flag.Options) (ScannerConfig, types.Scan AWSEndpoint: opts.Endpoint, FileChecksum: fileChecksum, DetectionPriority: opts.DetectionPriority, + IncludeDevDeps: opts.IncludeDevDeps, // For image scanning ImageOption: ftypes.ImageOptions{ diff --git a/pkg/dependency/parser/nodejs/npm/parse.go b/pkg/dependency/parser/nodejs/npm/parse.go index 05ce6301ff09..d913b56c5565 100644 --- a/pkg/dependency/parser/nodejs/npm/parse.go +++ b/pkg/dependency/parser/nodejs/npm/parse.go @@ -52,12 +52,14 @@ type Package struct { } type Parser struct { - logger *log.Logger + logger *log.Logger + includeDevDeps bool } -func NewParser() *Parser { +func NewParser(includeDevDeps bool) *Parser { return &Parser{ - logger: log.WithPrefix("npm"), + logger: log.WithPrefix("npm"), + includeDevDeps: includeDevDeps, } } @@ -108,6 +110,11 @@ func (p *Parser) parseV2(packages map[string]Package) ([]ftypes.Package, []ftype continue } + // Skip `Dev` dependencies if `--include-dev-deps` flag is not present + if pkg.Dev && !p.includeDevDeps { + continue + } + // pkg.Name exists when package name != folder name pkgName := pkg.Name if pkgName == "" { @@ -290,6 +297,11 @@ func (p *Parser) parseV1(dependencies map[string]Dependency, versions map[string var pkgs []ftypes.Package var deps []ftypes.Dependency for pkgName, dep := range dependencies { + // Skip `Dev` dependencies if `--include-dev-deps` flag is not present + if dep.Dev && !p.includeDevDeps { + continue + } + pkg := ftypes.Package{ ID: packageID(pkgName, dep.Version), Name: pkgName, diff --git a/pkg/dependency/parser/nodejs/npm/parse_test.go b/pkg/dependency/parser/nodejs/npm/parse_test.go index 7b0b5042c831..565595e0a7b1 100644 --- a/pkg/dependency/parser/nodejs/npm/parse_test.go +++ b/pkg/dependency/parser/nodejs/npm/parse_test.go @@ -12,46 +12,74 @@ import ( func TestParse(t *testing.T) { tests := []struct { - name string - file string // Test input file - want []ftypes.Package - wantDeps []ftypes.Dependency + name string + file string // Test input file + includeDevDeps bool + want []ftypes.Package + wantDeps []ftypes.Dependency }{ { - name: "lock version v1", - file: "testdata/package-lock_v1.json", - want: npmV1Pkgs, - wantDeps: npmDeps, + name: "lock version v1", + file: "testdata/package-lock_v1.json", + includeDevDeps: true, + want: npmV1Pkgs, + wantDeps: npmDeps, }, { - name: "lock version v2", - file: "testdata/package-lock_v2.json", - want: npmV2Pkgs, - wantDeps: npmDeps, + name: "lock version v1. Exclude Dev deps", + file: "testdata/package-lock_v1.json", + includeDevDeps: false, + want: npmV1PkgsExcludeDev, + wantDeps: npmDepsExcludeDev, }, { - name: "lock version v3", - file: "testdata/package-lock_v3.json", - want: npmV2Pkgs, - wantDeps: npmDeps, + name: "lock version v2", + file: "testdata/package-lock_v2.json", + includeDevDeps: true, + want: npmV2Pkgs, + wantDeps: npmDeps, }, { - name: "lock version v3 with workspace", - file: "testdata/package-lock_v3_with_workspace.json", - want: npmV3WithWorkspacePkgs, - wantDeps: npmV3WithWorkspaceDeps, + name: "lock version v3", + file: "testdata/package-lock_v3.json", + includeDevDeps: true, + want: npmV2Pkgs, + wantDeps: npmDeps, }, { - name: "lock file v3 contains same dev and non-dev dependencies", - file: "testdata/package-lock_v3_with-same-dev-and-non-dev.json", - want: npmV3WithSameDevAndNonDevPkgs, - wantDeps: npmV3WithSameDevAndNonDevDeps, + name: "lock version v3. Exclude Dev deps", + file: "testdata/package-lock_v3.json", + includeDevDeps: false, + want: npmV2PkgsExcludeDev, + wantDeps: npmV2DepsExcludeDev, }, { - name: "lock version v3 with workspace and without direct deps field", - file: "testdata/package-lock_v3_without_root_deps_field.json", - want: npmV3WithoutRootDepsField, - wantDeps: npmV3WithoutRootDepsFieldDeps, + name: "lock version v3 with workspace", + file: "testdata/package-lock_v3_with_workspace.json", + includeDevDeps: true, + want: npmV3WithWorkspacePkgs, + 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", + includeDevDeps: true, + want: npmV3WithSameDevAndNonDevPkgs, + wantDeps: npmV3WithSameDevAndNonDevDeps, + }, + { + name: "lock file v3 contains same dev and non-dev dependencies. Exclude Dev deps", + file: "testdata/package-lock_v3_with-same-dev-and-non-dev.json", + includeDevDeps: false, + want: npmV3WithSameDevAndNonDevPkgsExcludeDev, + wantDeps: nil, + }, + { + name: "lock version v3 with workspace and without direct deps field", + file: "testdata/package-lock_v3_without_root_deps_field.json", + includeDevDeps: true, + want: npmV3WithoutRootDepsField, + wantDeps: npmV3WithoutRootDepsFieldDeps, }, { name: "lock version v3 with broken link", @@ -66,7 +94,7 @@ func TestParse(t *testing.T) { f, err := os.Open(tt.file) require.NoError(t, err) - got, deps, err := NewParser().Parse(f) + got, deps, err := NewParser(tt.includeDevDeps).Parse(f) require.NoError(t, err) assert.Equal(t, tt.want, got) diff --git a/pkg/dependency/parser/nodejs/npm/parse_testcase.go b/pkg/dependency/parser/nodejs/npm/parse_testcase.go index 01dcac6711f9..0be0d534c425 100644 --- a/pkg/dependency/parser/nodejs/npm/parse_testcase.go +++ b/pkg/dependency/parser/nodejs/npm/parse_testcase.go @@ -1,6 +1,8 @@ package npm -import ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" +import ( + ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" +) var ( // docker run --name node --rm -it node@sha256:51dd437f31812df71108b81385e2945071ec813d5815fa3403855669c8f3432b sh @@ -692,20 +694,13 @@ var ( }, } - // ... and - // npm i --lockfile-version 2 - // same as npmV1Pkgs but change `Indirect` field to false for `body-parser@1.18.3`, `finalhandler@1.1.1`, `@babel/helper-string-parser@7.19.4`, `promise@8.3.0` and `ms@1.0.0` packages. - // also need to get locations from `packages` struct - // --- lockfile version 3 --- - // npm i --lockfile-version 3 - // same as npmV2Pkgs. - npmV2Pkgs = []ftypes.Package{ + npmV1PkgsExcludeDev = []ftypes.Package{ { ID: "@babel/helper-string-parser@7.19.4", Name: "@babel/helper-string-parser", Version: "7.19.4", Dev: false, - Relationship: ftypes.RelationshipDirect, + Relationship: ftypes.RelationshipUnknown, ExternalReferences: []ftypes.ExternalRef{ { Type: ftypes.RefOther, @@ -714,122 +709,46 @@ var ( }, Locations: []ftypes.Location{ { - StartLine: 24, - EndLine: 31, - }, - }, - }, - { - ID: "body-parser@1.18.3", - Name: "body-parser", - Version: "1.18.3", - Dev: false, - Relationship: ftypes.RelationshipDirect, - ExternalReferences: []ftypes.ExternalRef{ - { - Type: ftypes.RefOther, - URL: "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", - }, - }, - Locations: []ftypes.Location{ - { - StartLine: 38, - EndLine: 57, - }, - }, - }, - { - ID: "debug@2.5.2", - Name: "debug", - Version: "2.5.2", - Dev: true, - Relationship: ftypes.RelationshipDirect, - ExternalReferences: []ftypes.ExternalRef{ - { - Type: ftypes.RefOther, - URL: "https://registry.npmjs.org/debug/-/debug-2.5.2.tgz", - }, - }, - Locations: []ftypes.Location{ - { - StartLine: 87, - EndLine: 95, - }, - }, - }, - { - ID: "finalhandler@1.1.1", - Name: "finalhandler", - Version: "1.1.1", - Dev: false, - Relationship: ftypes.RelationshipDirect, - ExternalReferences: []ftypes.ExternalRef{ - { - Type: ftypes.RefOther, - URL: "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", - }, - }, - Locations: []ftypes.Location{ - { - StartLine: 128, - EndLine: 144, - }, - }, - }, - { - ID: "ms@1.0.0", - Name: "ms", - Version: "1.0.0", - Dev: false, - Relationship: ftypes.RelationshipDirect, - ExternalReferences: []ftypes.ExternalRef{ - { - Type: ftypes.RefOther, - URL: "https://registry.npmjs.org/ms/-/ms-1.0.0.tgz", - }, - }, - Locations: []ftypes.Location{ - { - StartLine: 215, - EndLine: 219, + StartLine: 7, + EndLine: 11, }, }, }, { - ID: "promise@8.3.0", - Name: "promise", - Version: "8.3.0", + ID: "asap@2.0.6", + Name: "asap", + Version: "2.0.6", Dev: false, - Relationship: ftypes.RelationshipDirect, + Relationship: ftypes.RelationshipUnknown, ExternalReferences: []ftypes.ExternalRef{ { Type: ftypes.RefOther, - URL: "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + URL: "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", }, }, Locations: []ftypes.Location{ { - StartLine: 239, - EndLine: 247, + StartLine: 12, + EndLine: 17, }, }, }, { - ID: "asap@2.0.6", - Name: "asap", - Version: "2.0.6", + ID: "body-parser@1.18.3", + Name: "body-parser", + Version: "1.18.3", Dev: false, - Relationship: ftypes.RelationshipIndirect, + Relationship: ftypes.RelationshipUnknown, ExternalReferences: []ftypes.ExternalRef{ { Type: ftypes.RefOther, - URL: "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + URL: "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", }, }, Locations: []ftypes.Location{ { - StartLine: 32, - EndLine: 37, + StartLine: 18, + EndLine: 49, }, }, }, @@ -838,7 +757,7 @@ var ( Name: "bytes", Version: "3.0.0", Dev: false, - Relationship: ftypes.RelationshipIndirect, + Relationship: ftypes.RelationshipUnknown, ExternalReferences: []ftypes.ExternalRef{ { Type: ftypes.RefOther, @@ -847,8 +766,8 @@ var ( }, Locations: []ftypes.Location{ { - StartLine: 71, - EndLine: 78, + StartLine: 50, + EndLine: 54, }, }, }, @@ -857,7 +776,7 @@ var ( Name: "content-type", Version: "1.0.5", Dev: false, - Relationship: ftypes.RelationshipIndirect, + Relationship: ftypes.RelationshipUnknown, ExternalReferences: []ftypes.ExternalRef{ { Type: ftypes.RefOther, @@ -866,8 +785,8 @@ var ( }, Locations: []ftypes.Location{ { - StartLine: 79, - EndLine: 86, + StartLine: 55, + EndLine: 59, }, }, }, @@ -876,7 +795,7 @@ var ( Name: "debug", Version: "2.6.9", Dev: false, - Relationship: ftypes.RelationshipIndirect, + Relationship: ftypes.RelationshipUnknown, ExternalReferences: []ftypes.ExternalRef{ { Type: ftypes.RefOther, @@ -885,12 +804,12 @@ var ( }, Locations: []ftypes.Location{ { - StartLine: 58, - EndLine: 65, + StartLine: 35, + EndLine: 42, }, { - StartLine: 145, - EndLine: 152, + StartLine: 111, + EndLine: 118, }, }, }, @@ -899,7 +818,7 @@ var ( Name: "depd", Version: "1.1.2", Dev: false, - Relationship: ftypes.RelationshipIndirect, + Relationship: ftypes.RelationshipUnknown, ExternalReferences: []ftypes.ExternalRef{ { Type: ftypes.RefOther, @@ -908,8 +827,8 @@ var ( }, Locations: []ftypes.Location{ { - StartLine: 102, - EndLine: 109, + StartLine: 77, + EndLine: 81, }, }, }, @@ -918,7 +837,7 @@ var ( Name: "ee-first", Version: "1.1.1", Dev: false, - Relationship: ftypes.RelationshipIndirect, + Relationship: ftypes.RelationshipUnknown, ExternalReferences: []ftypes.ExternalRef{ { Type: ftypes.RefOther, @@ -927,8 +846,8 @@ var ( }, Locations: []ftypes.Location{ { - StartLine: 110, - EndLine: 114, + StartLine: 82, + EndLine: 86, }, }, }, @@ -937,7 +856,7 @@ var ( Name: "encodeurl", Version: "1.0.2", Dev: false, - Relationship: ftypes.RelationshipIndirect, + Relationship: ftypes.RelationshipUnknown, ExternalReferences: []ftypes.ExternalRef{ { Type: ftypes.RefOther, @@ -946,8 +865,8 @@ var ( }, Locations: []ftypes.Location{ { - StartLine: 115, - EndLine: 122, + StartLine: 87, + EndLine: 91, }, }, }, @@ -956,7 +875,7 @@ var ( Name: "escape-html", Version: "1.0.3", Dev: false, - Relationship: ftypes.RelationshipIndirect, + Relationship: ftypes.RelationshipUnknown, ExternalReferences: []ftypes.ExternalRef{ { Type: ftypes.RefOther, @@ -965,8 +884,27 @@ var ( }, Locations: []ftypes.Location{ { - StartLine: 123, - EndLine: 127, + StartLine: 92, + EndLine: 96, + }, + }, + }, + { + ID: "finalhandler@1.1.1", + Name: "finalhandler", + Version: "1.1.1", + Dev: false, + Relationship: ftypes.RelationshipUnknown, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 97, + EndLine: 125, }, }, }, @@ -975,7 +913,7 @@ var ( Name: "http-errors", Version: "1.6.3", Dev: false, - Relationship: ftypes.RelationshipIndirect, + Relationship: ftypes.RelationshipUnknown, ExternalReferences: []ftypes.ExternalRef{ { Type: ftypes.RefOther, @@ -984,8 +922,8 @@ var ( }, Locations: []ftypes.Location{ { - StartLine: 158, - EndLine: 171, + StartLine: 126, + EndLine: 136, }, }, }, @@ -994,7 +932,7 @@ var ( Name: "iconv-lite", Version: "0.4.23", Dev: false, - Relationship: ftypes.RelationshipIndirect, + Relationship: ftypes.RelationshipUnknown, ExternalReferences: []ftypes.ExternalRef{ { Type: ftypes.RefOther, @@ -1003,8 +941,8 @@ var ( }, Locations: []ftypes.Location{ { - StartLine: 172, - EndLine: 182, + StartLine: 137, + EndLine: 144, }, }, }, @@ -1013,7 +951,7 @@ var ( Name: "inherits", Version: "2.0.3", Dev: false, - Relationship: ftypes.RelationshipIndirect, + Relationship: ftypes.RelationshipUnknown, ExternalReferences: []ftypes.ExternalRef{ { Type: ftypes.RefOther, @@ -1022,8 +960,8 @@ var ( }, Locations: []ftypes.Location{ { - StartLine: 183, - EndLine: 187, + StartLine: 145, + EndLine: 149, }, }, }, @@ -1032,7 +970,7 @@ var ( Name: "media-typer", Version: "0.3.0", Dev: false, - Relationship: ftypes.RelationshipIndirect, + Relationship: ftypes.RelationshipUnknown, ExternalReferences: []ftypes.ExternalRef{ { Type: ftypes.RefOther, @@ -1041,8 +979,8 @@ var ( }, Locations: []ftypes.Location{ { - StartLine: 188, - EndLine: 195, + StartLine: 150, + EndLine: 154, }, }, }, @@ -1051,7 +989,7 @@ var ( Name: "mime-db", Version: "1.52.0", Dev: false, - Relationship: ftypes.RelationshipIndirect, + Relationship: ftypes.RelationshipUnknown, ExternalReferences: []ftypes.ExternalRef{ { Type: ftypes.RefOther, @@ -1060,8 +998,8 @@ var ( }, Locations: []ftypes.Location{ { - StartLine: 196, - EndLine: 203, + StartLine: 155, + EndLine: 159, }, }, }, @@ -1070,7 +1008,7 @@ var ( Name: "mime-types", Version: "2.1.35", Dev: false, - Relationship: ftypes.RelationshipIndirect, + Relationship: ftypes.RelationshipUnknown, ExternalReferences: []ftypes.ExternalRef{ { Type: ftypes.RefOther, @@ -1079,27 +1017,27 @@ var ( }, Locations: []ftypes.Location{ { - StartLine: 204, - EndLine: 214, + StartLine: 160, + EndLine: 167, }, }, }, { - ID: "ms@0.7.2", + ID: "ms@1.0.0", Name: "ms", - Version: "0.7.2", - Dev: true, - Relationship: ftypes.RelationshipIndirect, + Version: "1.0.0", + Dev: false, + Relationship: ftypes.RelationshipUnknown, ExternalReferences: []ftypes.ExternalRef{ { Type: ftypes.RefOther, - URL: "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + URL: "https://registry.npmjs.org/ms/-/ms-1.0.0.tgz", }, }, Locations: []ftypes.Location{ { - StartLine: 96, - EndLine: 101, + StartLine: 168, + EndLine: 172, }, }, }, @@ -1108,7 +1046,7 @@ var ( Name: "ms", Version: "2.0.0", Dev: false, - Relationship: ftypes.RelationshipIndirect, + Relationship: ftypes.RelationshipUnknown, ExternalReferences: []ftypes.ExternalRef{ { Type: ftypes.RefOther, @@ -1117,12 +1055,12 @@ var ( }, Locations: []ftypes.Location{ { - StartLine: 66, - EndLine: 70, + StartLine: 43, + EndLine: 47, }, { - StartLine: 153, - EndLine: 157, + StartLine: 119, + EndLine: 123, }, }, }, @@ -1131,7 +1069,7 @@ var ( Name: "on-finished", Version: "2.3.0", Dev: false, - Relationship: ftypes.RelationshipIndirect, + Relationship: ftypes.RelationshipUnknown, ExternalReferences: []ftypes.ExternalRef{ { Type: ftypes.RefOther, @@ -1140,8 +1078,8 @@ var ( }, Locations: []ftypes.Location{ { - StartLine: 220, - EndLine: 230, + StartLine: 173, + EndLine: 180, }, }, }, @@ -1150,7 +1088,7 @@ var ( Name: "parseurl", Version: "1.3.3", Dev: false, - Relationship: ftypes.RelationshipIndirect, + Relationship: ftypes.RelationshipUnknown, ExternalReferences: []ftypes.ExternalRef{ { Type: ftypes.RefOther, @@ -1159,8 +1097,1272 @@ var ( }, Locations: []ftypes.Location{ { - StartLine: 231, - EndLine: 238, + StartLine: 181, + EndLine: 185, + }, + }, + }, + { + ID: "promise@8.3.0", + Name: "promise", + Version: "8.3.0", + Dev: false, + Relationship: ftypes.RelationshipUnknown, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 186, + EndLine: 194, + }, + }, + }, + { + ID: "qs@6.5.2", + Name: "qs", + Version: "6.5.2", + Dev: false, + Relationship: ftypes.RelationshipUnknown, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 195, + EndLine: 199, + }, + }, + }, + { + ID: "raw-body@2.3.3", + Name: "raw-body", + Version: "2.3.3", + Dev: false, + Relationship: ftypes.RelationshipUnknown, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 200, + EndLine: 210, + }, + }, + }, + { + ID: "safer-buffer@2.1.2", + Name: "safer-buffer", + Version: "2.1.2", + Dev: false, + Relationship: ftypes.RelationshipUnknown, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 211, + EndLine: 215, + }, + }, + }, + { + ID: "setprototypeof@1.1.0", + Name: "setprototypeof", + Version: "1.1.0", + Dev: false, + Relationship: ftypes.RelationshipUnknown, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 216, + EndLine: 220, + }, + }, + }, + { + ID: "statuses@1.4.0", + Name: "statuses", + Version: "1.4.0", + Dev: false, + Relationship: ftypes.RelationshipUnknown, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 221, + EndLine: 225, + }, + }, + }, + { + ID: "type-is@1.6.18", + Name: "type-is", + Version: "1.6.18", + Dev: false, + Relationship: ftypes.RelationshipUnknown, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 226, + EndLine: 234, + }, + }, + }, + { + ID: "unpipe@1.0.0", + Name: "unpipe", + Version: "1.0.0", + Dev: false, + Relationship: ftypes.RelationshipUnknown, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 235, + EndLine: 239, + }, + }, + }, + } + + // dependencies are filled manually + npmDepsExcludeDev = []ftypes.Dependency{ + { + ID: "body-parser@1.18.3", + DependsOn: []string{ + "bytes@3.0.0", + "content-type@1.0.5", + "debug@2.6.9", + "depd@1.1.2", + "http-errors@1.6.3", + "iconv-lite@0.4.23", + "on-finished@2.3.0", + "qs@6.5.2", + "raw-body@2.3.3", + "type-is@1.6.18", + }, + }, + { + ID: "debug@2.6.9", + DependsOn: []string{"ms@2.0.0"}, + }, + { + ID: "finalhandler@1.1.1", + DependsOn: []string{ + "debug@2.6.9", + "encodeurl@1.0.2", + "escape-html@1.0.3", + "on-finished@2.3.0", + "parseurl@1.3.3", + "statuses@1.4.0", + "unpipe@1.0.0", + }, + }, + { + ID: "http-errors@1.6.3", + DependsOn: []string{ + "depd@1.1.2", + "inherits@2.0.3", + "setprototypeof@1.1.0", + "statuses@1.4.0", + }, + }, + { + ID: "iconv-lite@0.4.23", + DependsOn: []string{"safer-buffer@2.1.2"}, + }, + { + ID: "mime-types@2.1.35", + DependsOn: []string{"mime-db@1.52.0"}, + }, + { + ID: "on-finished@2.3.0", + DependsOn: []string{"ee-first@1.1.1"}, + }, + { + ID: "promise@8.3.0", + DependsOn: []string{"asap@2.0.6"}, + }, + { + ID: "raw-body@2.3.3", + DependsOn: []string{ + "bytes@3.0.0", + "http-errors@1.6.3", + "iconv-lite@0.4.23", + "unpipe@1.0.0", + }, + }, + { + ID: "type-is@1.6.18", + DependsOn: []string{ + "media-typer@0.3.0", + "mime-types@2.1.35", + }, + }, + } + + // ... and + // npm i --lockfile-version 2 + // same as npmV1Pkgs but change `Indirect` field to false for `body-parser@1.18.3`, `finalhandler@1.1.1`, `@babel/helper-string-parser@7.19.4`, `promise@8.3.0` and `ms@1.0.0` packages. + // also need to get locations from `packages` struct + // --- lockfile version 3 --- + // npm i --lockfile-version 3 + // same as npmV2Pkgs. + npmV2Pkgs = []ftypes.Package{ + { + ID: "@babel/helper-string-parser@7.19.4", + Name: "@babel/helper-string-parser", + Version: "7.19.4", + Dev: false, + Relationship: ftypes.RelationshipDirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 24, + EndLine: 31, + }, + }, + }, + { + ID: "body-parser@1.18.3", + Name: "body-parser", + Version: "1.18.3", + Dev: false, + Relationship: ftypes.RelationshipDirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 38, + EndLine: 57, + }, + }, + }, + { + ID: "debug@2.5.2", + Name: "debug", + Version: "2.5.2", + Dev: true, + Relationship: ftypes.RelationshipDirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/debug/-/debug-2.5.2.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 87, + EndLine: 95, + }, + }, + }, + { + ID: "finalhandler@1.1.1", + Name: "finalhandler", + Version: "1.1.1", + Dev: false, + Relationship: ftypes.RelationshipDirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 128, + EndLine: 144, + }, + }, + }, + { + ID: "ms@1.0.0", + Name: "ms", + Version: "1.0.0", + Dev: false, + Relationship: ftypes.RelationshipDirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/ms/-/ms-1.0.0.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 215, + EndLine: 219, + }, + }, + }, + { + ID: "promise@8.3.0", + Name: "promise", + Version: "8.3.0", + Dev: false, + Relationship: ftypes.RelationshipDirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 239, + EndLine: 247, + }, + }, + }, + { + ID: "asap@2.0.6", + Name: "asap", + Version: "2.0.6", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 32, + EndLine: 37, + }, + }, + }, + { + ID: "bytes@3.0.0", + Name: "bytes", + Version: "3.0.0", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 71, + EndLine: 78, + }, + }, + }, + { + ID: "content-type@1.0.5", + Name: "content-type", + Version: "1.0.5", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 79, + EndLine: 86, + }, + }, + }, + { + ID: "debug@2.6.9", + Name: "debug", + Version: "2.6.9", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 58, + EndLine: 65, + }, + { + StartLine: 145, + EndLine: 152, + }, + }, + }, + { + ID: "depd@1.1.2", + Name: "depd", + Version: "1.1.2", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 102, + EndLine: 109, + }, + }, + }, + { + ID: "ee-first@1.1.1", + Name: "ee-first", + Version: "1.1.1", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 110, + EndLine: 114, + }, + }, + }, + { + ID: "encodeurl@1.0.2", + Name: "encodeurl", + Version: "1.0.2", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 115, + EndLine: 122, + }, + }, + }, + { + ID: "escape-html@1.0.3", + Name: "escape-html", + Version: "1.0.3", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 123, + EndLine: 127, + }, + }, + }, + { + ID: "http-errors@1.6.3", + Name: "http-errors", + Version: "1.6.3", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 158, + EndLine: 171, + }, + }, + }, + { + ID: "iconv-lite@0.4.23", + Name: "iconv-lite", + Version: "0.4.23", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 172, + EndLine: 182, + }, + }, + }, + { + ID: "inherits@2.0.3", + Name: "inherits", + Version: "2.0.3", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 183, + EndLine: 187, + }, + }, + }, + { + ID: "media-typer@0.3.0", + Name: "media-typer", + Version: "0.3.0", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 188, + EndLine: 195, + }, + }, + }, + { + ID: "mime-db@1.52.0", + Name: "mime-db", + Version: "1.52.0", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 196, + EndLine: 203, + }, + }, + }, + { + ID: "mime-types@2.1.35", + Name: "mime-types", + Version: "2.1.35", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 204, + EndLine: 214, + }, + }, + }, + { + ID: "ms@0.7.2", + Name: "ms", + Version: "0.7.2", + Dev: true, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 96, + EndLine: 101, + }, + }, + }, + { + ID: "ms@2.0.0", + Name: "ms", + Version: "2.0.0", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 66, + EndLine: 70, + }, + { + StartLine: 153, + EndLine: 157, + }, + }, + }, + { + ID: "on-finished@2.3.0", + Name: "on-finished", + Version: "2.3.0", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 220, + EndLine: 230, + }, + }, + }, + { + ID: "parseurl@1.3.3", + Name: "parseurl", + Version: "1.3.3", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 231, + EndLine: 238, + }, + }, + }, + { + ID: "qs@6.5.2", + Name: "qs", + Version: "6.5.2", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 248, + EndLine: 255, + }, + }, + }, + { + ID: "raw-body@2.3.3", + Name: "raw-body", + Version: "2.3.3", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 256, + EndLine: 269, + }, + }, + }, + { + ID: "safer-buffer@2.1.2", + Name: "safer-buffer", + Version: "2.1.2", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 270, + EndLine: 274, + }, + }, + }, + { + ID: "setprototypeof@1.1.0", + Name: "setprototypeof", + Version: "1.1.0", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 275, + EndLine: 279, + }, + }, + }, + { + ID: "statuses@1.4.0", + Name: "statuses", + Version: "1.4.0", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 280, + EndLine: 287, + }, + }, + }, + { + ID: "type-is@1.6.18", + Name: "type-is", + Version: "1.6.18", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 288, + EndLine: 299, + }, + }, + }, + { + ID: "unpipe@1.0.0", + Name: "unpipe", + Version: "1.0.0", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 300, + EndLine: 307, + }, + }, + }, + } + + npmV2PkgsExcludeDev = []ftypes.Package{ + { + ID: "@babel/helper-string-parser@7.19.4", + Name: "@babel/helper-string-parser", + Version: "7.19.4", + Dev: false, + Relationship: ftypes.RelationshipDirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 24, + EndLine: 31, + }, + }, + }, + { + ID: "body-parser@1.18.3", + Name: "body-parser", + Version: "1.18.3", + Dev: false, + Relationship: ftypes.RelationshipDirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 38, + EndLine: 57, + }, + }, + }, + { + ID: "finalhandler@1.1.1", + Name: "finalhandler", + Version: "1.1.1", + Dev: false, + Relationship: ftypes.RelationshipDirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 128, + EndLine: 144, + }, + }, + }, + { + ID: "ms@1.0.0", + Name: "ms", + Version: "1.0.0", + Dev: false, + Relationship: ftypes.RelationshipDirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/ms/-/ms-1.0.0.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 215, + EndLine: 219, + }, + }, + }, + { + ID: "promise@8.3.0", + Name: "promise", + Version: "8.3.0", + Dev: false, + Relationship: ftypes.RelationshipDirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 239, + EndLine: 247, + }, + }, + }, + { + ID: "asap@2.0.6", + Name: "asap", + Version: "2.0.6", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 32, + EndLine: 37, + }, + }, + }, + { + ID: "bytes@3.0.0", + Name: "bytes", + Version: "3.0.0", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 71, + EndLine: 78, + }, + }, + }, + { + ID: "content-type@1.0.5", + Name: "content-type", + Version: "1.0.5", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 79, + EndLine: 86, + }, + }, + }, + { + ID: "debug@2.6.9", + Name: "debug", + Version: "2.6.9", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 58, + EndLine: 65, + }, + { + StartLine: 145, + EndLine: 152, + }, + }, + }, + { + ID: "depd@1.1.2", + Name: "depd", + Version: "1.1.2", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 102, + EndLine: 109, + }, + }, + }, + { + ID: "ee-first@1.1.1", + Name: "ee-first", + Version: "1.1.1", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 110, + EndLine: 114, + }, + }, + }, + { + ID: "encodeurl@1.0.2", + Name: "encodeurl", + Version: "1.0.2", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 115, + EndLine: 122, + }, + }, + }, + { + ID: "escape-html@1.0.3", + Name: "escape-html", + Version: "1.0.3", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 123, + EndLine: 127, + }, + }, + }, + { + ID: "http-errors@1.6.3", + Name: "http-errors", + Version: "1.6.3", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 158, + EndLine: 171, + }, + }, + }, + { + ID: "iconv-lite@0.4.23", + Name: "iconv-lite", + Version: "0.4.23", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 172, + EndLine: 182, + }, + }, + }, + { + ID: "inherits@2.0.3", + Name: "inherits", + Version: "2.0.3", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 183, + EndLine: 187, + }, + }, + }, + { + ID: "media-typer@0.3.0", + Name: "media-typer", + Version: "0.3.0", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 188, + EndLine: 195, + }, + }, + }, + { + ID: "mime-db@1.52.0", + Name: "mime-db", + Version: "1.52.0", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 196, + EndLine: 203, + }, + }, + }, + { + ID: "mime-types@2.1.35", + Name: "mime-types", + Version: "2.1.35", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 204, + EndLine: 214, + }, + }, + }, + { + ID: "ms@2.0.0", + Name: "ms", + Version: "2.0.0", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 66, + EndLine: 70, + }, + { + StartLine: 153, + EndLine: 157, + }, + }, + }, + { + ID: "on-finished@2.3.0", + Name: "on-finished", + Version: "2.3.0", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 220, + EndLine: 230, + }, + }, + }, + { + ID: "parseurl@1.3.3", + Name: "parseurl", + Version: "1.3.3", + Dev: false, + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 231, + EndLine: 238, }, }, }, @@ -1299,6 +2501,81 @@ var ( }, } + npmV2DepsExcludeDev = []ftypes.Dependency{ + { + ID: "body-parser@1.18.3", + DependsOn: []string{ + "bytes@3.0.0", + "content-type@1.0.5", + "debug@2.6.9", + "depd@1.1.2", + "http-errors@1.6.3", + "iconv-lite@0.4.23", + "on-finished@2.3.0", + "qs@6.5.2", + "raw-body@2.3.3", + "type-is@1.6.18", + }, + }, + { + ID: "debug@2.6.9", + DependsOn: []string{"ms@2.0.0"}, + }, + { + ID: "finalhandler@1.1.1", + DependsOn: []string{ + "debug@2.6.9", + "encodeurl@1.0.2", + "escape-html@1.0.3", + "on-finished@2.3.0", + "parseurl@1.3.3", + "statuses@1.4.0", + "unpipe@1.0.0", + }, + }, + { + ID: "http-errors@1.6.3", + DependsOn: []string{ + "depd@1.1.2", + "inherits@2.0.3", + "setprototypeof@1.1.0", + "statuses@1.4.0", + }, + }, + { + ID: "iconv-lite@0.4.23", + DependsOn: []string{"safer-buffer@2.1.2"}, + }, + { + ID: "mime-types@2.1.35", + DependsOn: []string{"mime-db@1.52.0"}, + }, + { + ID: "on-finished@2.3.0", + DependsOn: []string{"ee-first@1.1.1"}, + }, + { + ID: "promise@8.3.0", + DependsOn: []string{"asap@2.0.6"}, + }, + { + ID: "raw-body@2.3.3", + DependsOn: []string{ + "bytes@3.0.0", + "http-errors@1.6.3", + "iconv-lite@0.4.23", + "unpipe@1.0.0", + }, + }, + { + ID: "type-is@1.6.18", + DependsOn: []string{ + "media-typer@0.3.0", + "mime-types@2.1.35", + }, + }, + } + // docker run --name node --rm -it node@sha256:51dd437f31812df71108b81385e2945071ec813d5815fa3403855669c8f3432b sh // mkdir node_v3_with_workspace && cd node_v3_with_workspace // npm init --force @@ -1602,4 +2879,26 @@ var ( DependsOn: []string{"mkdirp@0.5.1"}, }, } + + npmV3WithSameDevAndNonDevPkgsExcludeDev = []ftypes.Package{ + { + ID: "minimist@0.0.8", + Name: "minimist", + Version: "0.0.8", + Relationship: ftypes.RelationshipDirect, + Dev: false, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefOther, + URL: "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + }, + }, + Locations: []ftypes.Location{ + { + StartLine: 68, + EndLine: 72, + }, + }, + }, + } ) diff --git a/pkg/fanal/analyzer/analyzer.go b/pkg/fanal/analyzer/analyzer.go index abedb4b90638..04289daf1334 100644 --- a/pkg/fanal/analyzer/analyzer.go +++ b/pkg/fanal/analyzer/analyzer.go @@ -44,6 +44,7 @@ type AnalyzerOptions struct { Parallel int FilePatterns []string DisabledAnalyzers []Type + IncludeDevDeps bool DetectionPriority types.DetectionPriority MisconfScannerOption misconf.ScannerOption SecretScannerOption SecretScannerOption diff --git a/pkg/fanal/analyzer/language/java/pom/pom.go b/pkg/fanal/analyzer/language/java/pom/pom.go index 382a41dc0f1c..acf16cae23de 100644 --- a/pkg/fanal/analyzer/language/java/pom/pom.go +++ b/pkg/fanal/analyzer/language/java/pom/pom.go @@ -21,10 +21,18 @@ func init() { const version = 1 // pomAnalyzer analyzes pom.xml -type pomAnalyzer struct{} +type pomAnalyzer struct { + includeDevDeps bool +} -func (a pomAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInput) (*analyzer.AnalysisResult, error) { +func (a *pomAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInput) (*analyzer.AnalysisResult, error) { filePath := filepath.Join(input.Dir, input.FilePath) + + // Skip integration test dir if `--include-dev-deps` flag is not present. + if isIntegrationTestDir(filePath) && !a.includeDevDeps { + return nil, nil + } + p := pom.NewParser(filePath, pom.WithOffline(input.Options.Offline)) res, err := language.Analyze(types.Pom, input.FilePath, input.Content, p) if err != nil { @@ -43,18 +51,23 @@ func (a pomAnalyzer) Analyze(_ context.Context, input analyzer.AnalysisInput) (* return res, nil } -func (a pomAnalyzer) Required(filePath string, _ os.FileInfo) bool { +func (a *pomAnalyzer) Required(filePath string, _ os.FileInfo) bool { return filepath.Base(filePath) == types.MavenPom } -func (a pomAnalyzer) Type() analyzer.Type { +func (a *pomAnalyzer) Type() analyzer.Type { return analyzer.TypePom } -func (a pomAnalyzer) Version() int { +func (a *pomAnalyzer) Version() int { return version } +func (a *pomAnalyzer) Init(opts analyzer.AnalyzerOptions) error { + a.includeDevDeps = opts.IncludeDevDeps + return nil +} + // isIntegrationTestDir checks that pom file is in directory with integration tests of `maven-invoker-plugin` // https://maven.apache.org/plugins/maven-invoker-plugin/usage.html func isIntegrationTestDir(filePath string) bool { diff --git a/pkg/fanal/analyzer/language/java/pom/pom_test.go b/pkg/fanal/analyzer/language/java/pom/pom_test.go index b3aaf43a82cf..698224ab37ea 100644 --- a/pkg/fanal/analyzer/language/java/pom/pom_test.go +++ b/pkg/fanal/analyzer/language/java/pom/pom_test.go @@ -14,11 +14,12 @@ import ( func Test_pomAnalyzer_Analyze(t *testing.T) { tests := []struct { - name string - inputDir string - inputFile string - want *analyzer.AnalysisResult - wantErr string + name string + inputDir string + inputFile string + includeDevDeps bool + want *analyzer.AnalysisResult + wantErr string }{ { name: "happy path", @@ -94,8 +95,9 @@ func Test_pomAnalyzer_Analyze(t *testing.T) { }, }, { - name: "happy path for maven-invoker-plugin integration tests", - inputFile: "testdata/mark-as-dev/src/it/example/pom.xml", + name: "happy path for maven-invoker-plugin integration tests", + inputFile: "testdata/mark-as-dev/src/it/example/pom.xml", + includeDevDeps: true, want: &analyzer.AnalysisResult{ Applications: []types.Application{ { @@ -131,6 +133,12 @@ func Test_pomAnalyzer_Analyze(t *testing.T) { }, }, }, + { + name: "happy path for maven-invoker-plugin integration tests without `--include-dev-deps` flag", + inputFile: "testdata/mark-as-dev/src/it/example/pom.xml", + includeDevDeps: false, + want: nil, + }, { name: "unsupported requirement", inputFile: "testdata/requirements/pom.xml", @@ -170,7 +178,9 @@ func Test_pomAnalyzer_Analyze(t *testing.T) { require.NoError(t, err) defer f.Close() - a := pomAnalyzer{} + a := pomAnalyzer{ + includeDevDeps: tt.includeDevDeps, + } got, err := a.Analyze(nil, analyzer.AnalysisInput{ Dir: tt.inputDir, FilePath: tt.inputFile, diff --git a/pkg/fanal/analyzer/language/nodejs/npm/npm.go b/pkg/fanal/analyzer/language/nodejs/npm/npm.go index 870ba1be88e7..d73dc8d2c0ef 100644 --- a/pkg/fanal/analyzer/language/nodejs/npm/npm.go +++ b/pkg/fanal/analyzer/language/nodejs/npm/npm.go @@ -36,10 +36,10 @@ type npmLibraryAnalyzer struct { packageParser *packagejson.Parser } -func newNpmLibraryAnalyzer(_ analyzer.AnalyzerOptions) (analyzer.PostAnalyzer, error) { +func newNpmLibraryAnalyzer(opts analyzer.AnalyzerOptions) (analyzer.PostAnalyzer, error) { return &npmLibraryAnalyzer{ logger: log.WithPrefix("npm"), - lockParser: npm.NewParser(), + lockParser: npm.NewParser(opts.IncludeDevDeps), packageParser: packagejson.NewParser(), }, nil } diff --git a/pkg/fanal/analyzer/language/nodejs/npm/npm_test.go b/pkg/fanal/analyzer/language/nodejs/npm/npm_test.go index 695fa80e040d..a60dfab86ab9 100644 --- a/pkg/fanal/analyzer/language/nodejs/npm/npm_test.go +++ b/pkg/fanal/analyzer/language/nodejs/npm/npm_test.go @@ -232,7 +232,9 @@ func Test_npmLibraryAnalyzer_Analyze(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - a, err := newNpmLibraryAnalyzer(analyzer.AnalyzerOptions{}) + a, err := newNpmLibraryAnalyzer(analyzer.AnalyzerOptions{ + IncludeDevDeps: true, + }) require.NoError(t, err) got, err := a.PostAnalyze(context.Background(), analyzer.PostAnalysisInput{ diff --git a/pkg/fanal/analyzer/language/nodejs/yarn/yarn.go b/pkg/fanal/analyzer/language/nodejs/yarn/yarn.go index 984f72983ec9..2adb90bec4ab 100644 --- a/pkg/fanal/analyzer/language/nodejs/yarn/yarn.go +++ b/pkg/fanal/analyzer/language/nodejs/yarn/yarn.go @@ -45,15 +45,17 @@ type yarnAnalyzer struct { logger *log.Logger packageJsonParser *packagejson.Parser comparer npm.Comparer + includeDevDeps bool license *license.License } -func newYarnAnalyzer(opt analyzer.AnalyzerOptions) (analyzer.PostAnalyzer, error) { +func newYarnAnalyzer(opts analyzer.AnalyzerOptions) (analyzer.PostAnalyzer, error) { return &yarnAnalyzer{ logger: log.WithPrefix("yarn"), packageJsonParser: packagejson.NewParser(), comparer: npm.Comparer{}, - license: license.NewLicense(opt.LicenseScannerOption.ClassifierConfidenceLevel), + includeDevDeps: opts.IncludeDevDeps, + license: license.NewLicense(opts.LicenseScannerOption.ClassifierConfidenceLevel), }, nil } @@ -183,9 +185,12 @@ func (a yarnAnalyzer) analyzeDependencies(fsys fs.FS, dir string, app *types.App } // Walk dev dependencies - devPkgs, err := a.walkDependencies(app.Packages, pkgIDs, directDevDeps, patterns, true) - if err != nil { - return xerrors.Errorf("unable to walk dependencies: %w", err) + var devPkgs = make(map[string]types.Package) + if a.includeDevDeps { + devPkgs, err = a.walkDependencies(app.Packages, pkgIDs, directDevDeps, patterns, true) + if err != nil { + return xerrors.Errorf("unable to walk dependencies: %w", err) + } } // Merge prod and dev dependencies. diff --git a/pkg/fanal/analyzer/language/nodejs/yarn/yarn_test.go b/pkg/fanal/analyzer/language/nodejs/yarn/yarn_test.go index 6684f0fa4740..ee963f635d5f 100644 --- a/pkg/fanal/analyzer/language/nodejs/yarn/yarn_test.go +++ b/pkg/fanal/analyzer/language/nodejs/yarn/yarn_test.go @@ -14,13 +14,15 @@ import ( func Test_yarnLibraryAnalyzer_Analyze(t *testing.T) { tests := []struct { - name string - dir string - want *analyzer.AnalysisResult + name string + dir string + includeDevDeps bool + want *analyzer.AnalysisResult }{ { - name: "happy path", - dir: "testdata/happy", + name: "happy path", + dir: "testdata/happy", + includeDevDeps: false, want: &analyzer.AnalysisResult{ Applications: []types.Application{ { @@ -39,24 +41,6 @@ func Test_yarnLibraryAnalyzer_Analyze(t *testing.T) { }, }, }, - { - ID: "prop-types@15.7.2", - Name: "prop-types", - Version: "15.7.2", - Dev: true, - Relationship: types.RelationshipDirect, - Locations: []types.Location{ - { - StartLine: 27, - EndLine: 34, - }, - }, - DependsOn: []string{ - "loose-envify@1.4.0", - "object-assign@4.1.1", - "react-is@16.13.1", - }, - }, { ID: "scheduler@0.13.6", Name: "scheduler", @@ -115,20 +99,6 @@ func Test_yarnLibraryAnalyzer_Analyze(t *testing.T) { }, }, }, - { - ID: "react-is@16.13.1", - Name: "react-is", - Version: "16.13.1", - Dev: true, - Indirect: true, - Relationship: types.RelationshipIndirect, - Locations: []types.Location{ - { - StartLine: 36, - EndLine: 39, - }, - }, - }, }, }, }, @@ -355,8 +325,9 @@ func Test_yarnLibraryAnalyzer_Analyze(t *testing.T) { }, }, { - name: "package uses `latest` version", - dir: "testdata/latest-version", + name: "package uses `latest` version", + dir: "testdata/latest-version", + includeDevDeps: true, want: &analyzer.AnalysisResult{ Applications: []types.Application{ { @@ -410,8 +381,9 @@ func Test_yarnLibraryAnalyzer_Analyze(t *testing.T) { }, }, { - name: "happy path with alias rewrite", - dir: "testdata/alias", + name: "happy path with alias rewrite", + dir: "testdata/alias", + includeDevDeps: true, want: &analyzer.AnalysisResult{ Applications: []types.Application{ { @@ -528,8 +500,9 @@ func Test_yarnLibraryAnalyzer_Analyze(t *testing.T) { }, }, { - name: "monorepo", - dir: "testdata/monorepo", + name: "monorepo", + dir: "testdata/monorepo", + includeDevDeps: true, want: &analyzer.AnalysisResult{ Applications: []types.Application{ { @@ -819,7 +792,7 @@ func Test_yarnLibraryAnalyzer_Analyze(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - a, err := newYarnAnalyzer(analyzer.AnalyzerOptions{}) + a, err := newYarnAnalyzer(analyzer.AnalyzerOptions{IncludeDevDeps: tt.includeDevDeps}) require.NoError(t, err) got, err := a.PostAnalyze(context.Background(), analyzer.PostAnalysisInput{ diff --git a/pkg/fanal/artifact/artifact.go b/pkg/fanal/artifact/artifact.go index b6034cb5ac63..febccc05b90d 100644 --- a/pkg/fanal/artifact/artifact.go +++ b/pkg/fanal/artifact/artifact.go @@ -29,6 +29,7 @@ type Option struct { AWSEndpoint string FileChecksum bool // For SPDX DetectionPriority types.DetectionPriority + IncludeDevDeps bool // Git repositories RepoBranch string @@ -51,6 +52,7 @@ func (o *Option) AnalyzerOptions() analyzer.AnalyzerOptions { FilePatterns: o.FilePatterns, Parallel: o.Parallel, DisabledAnalyzers: o.DisabledAnalyzers, + IncludeDevDeps: o.IncludeDevDeps, DetectionPriority: o.DetectionPriority, MisconfScannerOption: o.MisconfScannerOption, SecretScannerOption: o.SecretScannerOption, diff --git a/pkg/scanner/local/scan.go b/pkg/scanner/local/scan.go index f34723058e06..0e8514321371 100644 --- a/pkg/scanner/local/scan.go +++ b/pkg/scanner/local/scan.go @@ -7,7 +7,6 @@ import ( "slices" "sort" "strings" - "sync" "github.com/google/wire" "github.com/samber/lo" @@ -108,8 +107,8 @@ func (s Scanner) Scan(ctx context.Context, targetName, artifactKey string, blobK func (s Scanner) ScanTarget(ctx context.Context, target types.ScanTarget, options types.ScanOptions) (types.Results, ftypes.OS, error) { var results types.Results - // Filter packages according to the options - excludePackages(&target, options) + // Filter packages by relationship + filterPkgByRelationship(&target, options) // Add packages if needed and scan packages for vulnerabilities vulnResults, eosl, err := s.scanVulnerabilities(ctx, target, options) @@ -404,15 +403,6 @@ func ShouldScanMisconfigOrRbac(scanners types.Scanners) bool { return scanners.AnyEnabled(types.MisconfigScanner, types.RBACScanner) } -func excludePackages(target *types.ScanTarget, options types.ScanOptions) { - // Filter packages by relationship - filterPkgByRelationship(target, options) - - // By default, development packages are removed from the result - // '--include-dev-deps' option allows including them - excludeDevDeps(target.Applications, options.IncludeDevDeps) -} - func filterPkgByRelationship(target *types.ScanTarget, options types.ScanOptions) { if slices.Compare(options.PkgRelationships, ftypes.Relationships) == 0 { return // No need to filter @@ -430,25 +420,6 @@ func filterPkgByRelationship(target *types.ScanTarget, options types.ScanOptions } } -// excludeDevDeps removes development dependencies from the list of applications -func excludeDevDeps(apps []ftypes.Application, include bool) { - if include { - return - } - - onceInfo := sync.OnceFunc(func() { - log.Info("Suppressing dependencies for development and testing. To display them, try the '--include-dev-deps' flag.") - }) - for i := range apps { - apps[i].Packages = lo.Filter(apps[i].Packages, func(lib ftypes.Package, index int) bool { - if lib.Dev { - onceInfo() - } - return !lib.Dev - }) - } -} - func mergePkgs(pkgs, pkgsFromCommands []ftypes.Package, options types.ScanOptions) []ftypes.Package { if !options.ScanRemovedPackages || len(pkgsFromCommands) == 0 { return pkgs