mirror of
https://github.com/anchore/syft.git
synced 2026-08-20 00:58:31 +02:00
Fix missing nested packages in package-lock.json v1 (#5108)
* fix(javascript): catalog nested package-lock v1 dependencies Signed-off-by: Eljees <57435526+Eljees@users.noreply.github.com> * test(javascript): cover nested package-lock v1 dependencies Signed-off-by: Eljees <57435526+Eljees@users.noreply.github.com> --------- Signed-off-by: Eljees <57435526+Eljees@users.noreply.github.com>
This commit is contained in:
parent
295454945c
commit
1286689419
@ -31,6 +31,7 @@ type lockDependency struct {
|
|||||||
Resolved string `json:"resolved"`
|
Resolved string `json:"resolved"`
|
||||||
Integrity string `json:"integrity"`
|
Integrity string `json:"integrity"`
|
||||||
Dev bool `json:"dev"`
|
Dev bool `json:"dev"`
|
||||||
|
Dependencies map[string]lockDependency `json:"dependencies"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type lockPackage struct {
|
type lockPackage struct {
|
||||||
@ -77,14 +78,7 @@ func (a genericPackageLockAdapter) parsePackageLock(ctx context.Context, resolve
|
|||||||
}
|
}
|
||||||
|
|
||||||
if lock.LockfileVersion == 1 {
|
if lock.LockfileVersion == 1 {
|
||||||
for name, pkgMeta := range lock.Dependencies {
|
pkgs = append(pkgs, a.packageLockV1Packages(ctx, resolver, reader.Location, lock.Dependencies)...)
|
||||||
// skip packages that are only present as a dev dependency
|
|
||||||
if !a.cfg.IncludeDevDependencies && pkgMeta.Dev {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
pkgs = append(pkgs, newPackageLockV1Package(ctx, a.cfg, resolver, reader.Location, name, pkgMeta))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if lock.LockfileVersion == 2 || lock.LockfileVersion == 3 {
|
if lock.LockfileVersion == 2 || lock.LockfileVersion == 3 {
|
||||||
@ -116,6 +110,32 @@ func (a genericPackageLockAdapter) parsePackageLock(ctx context.Context, resolve
|
|||||||
return pkgs, dependency.Resolve(packageLockDependencySpecifier, pkgs), unknown.IfEmptyf(pkgs, "unable to determine packages")
|
return pkgs, dependency.Resolve(packageLockDependencySpecifier, pkgs), unknown.IfEmptyf(pkgs, "unable to determine packages")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a genericPackageLockAdapter) packageLockV1Packages(ctx context.Context, resolver file.Resolver, location file.Location, dependencies map[string]lockDependency) []pkg.Package {
|
||||||
|
var pkgs []pkg.Package
|
||||||
|
seen := make(map[string]struct{})
|
||||||
|
|
||||||
|
var walk func(map[string]lockDependency)
|
||||||
|
walk = func(dependencies map[string]lockDependency) {
|
||||||
|
for name, pkgMeta := range dependencies {
|
||||||
|
// Skipping a dev-only dependency also skips its dev-only subtree.
|
||||||
|
if !a.cfg.IncludeDevDependencies && pkgMeta.Dev {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
p := newPackageLockV1Package(ctx, a.cfg, resolver, location, name, pkgMeta)
|
||||||
|
if _, exists := seen[p.PURL]; !exists {
|
||||||
|
pkgs = append(pkgs, p)
|
||||||
|
seen[p.PURL] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
walk(pkgMeta.Dependencies)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
walk(dependencies)
|
||||||
|
return pkgs
|
||||||
|
}
|
||||||
|
|
||||||
func (licenses *packageLockLicense) UnmarshalJSON(data []byte) (err error) {
|
func (licenses *packageLockLicense) UnmarshalJSON(data []byte) (err error) {
|
||||||
// The license field could be either a string or an array.
|
// The license field could be either a string or an array.
|
||||||
|
|
||||||
|
|||||||
@ -111,6 +111,66 @@ func TestParsePackageLock(t *testing.T) {
|
|||||||
pkgtest.TestFileParser(t, fixture, adapter.parsePackageLock, expectedPkgs, expectedRelationships)
|
pkgtest.TestFileParser(t, fixture, adapter.parsePackageLock, expectedPkgs, expectedRelationships)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParsePackageLockV1NestedDependencies(t *testing.T) {
|
||||||
|
fixture := "testdata/pkg-lock/nested-package-lock-1.json"
|
||||||
|
expectedPkgs := []pkg.Package{
|
||||||
|
{
|
||||||
|
Name: "duplicate",
|
||||||
|
Version: "1.0.0",
|
||||||
|
PURL: "pkg:npm/duplicate@1.0.0",
|
||||||
|
Language: pkg.JavaScript,
|
||||||
|
Type: pkg.NpmPkg,
|
||||||
|
Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/duplicate/-/duplicate-1.0.0.tgz", Integrity: "sha512-duplicate"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "middle",
|
||||||
|
Version: "1.0.0",
|
||||||
|
PURL: "pkg:npm/middle@1.0.0",
|
||||||
|
Language: pkg.JavaScript,
|
||||||
|
Type: pkg.NpmPkg,
|
||||||
|
Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/middle/-/middle-1.0.0.tgz", Integrity: "sha512-middle"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "parent",
|
||||||
|
Version: "1.0.0",
|
||||||
|
PURL: "pkg:npm/parent@1.0.0",
|
||||||
|
Language: pkg.JavaScript,
|
||||||
|
Type: pkg.NpmPkg,
|
||||||
|
Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/parent/-/parent-1.0.0.tgz", Integrity: "sha512-parent"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "shared",
|
||||||
|
Version: "0.5.0",
|
||||||
|
PURL: "pkg:npm/shared@0.5.0",
|
||||||
|
Language: pkg.JavaScript,
|
||||||
|
Type: pkg.NpmPkg,
|
||||||
|
Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/shared/-/shared-0.5.0.tgz", Integrity: "sha512-shared-0.5"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "shared",
|
||||||
|
Version: "1.0.0",
|
||||||
|
PURL: "pkg:npm/shared@1.0.0",
|
||||||
|
Language: pkg.JavaScript,
|
||||||
|
Type: pkg.NpmPkg,
|
||||||
|
Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/shared/-/shared-1.0.0.tgz", Integrity: "sha512-shared-1"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "shared",
|
||||||
|
Version: "2.0.0",
|
||||||
|
PURL: "pkg:npm/shared@2.0.0",
|
||||||
|
Language: pkg.JavaScript,
|
||||||
|
Type: pkg.NpmPkg,
|
||||||
|
Metadata: pkg.NpmPackageLockEntry{Resolved: "https://registry.npmjs.org/shared/-/shared-2.0.0.tgz", Integrity: "sha512-shared-2"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for i := range expectedPkgs {
|
||||||
|
expectedPkgs[i].Locations.Add(file.NewLocation(fixture))
|
||||||
|
}
|
||||||
|
|
||||||
|
adapter := newGenericPackageLockAdapter(CatalogerConfig{})
|
||||||
|
pkgtest.TestFileParser(t, fixture, adapter.parsePackageLock, expectedPkgs, nil)
|
||||||
|
}
|
||||||
|
|
||||||
func TestParsePackageLockV2(t *testing.T) {
|
func TestParsePackageLockV2(t *testing.T) {
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
fixture := "testdata/pkg-lock/package-lock-2.json"
|
fixture := "testdata/pkg-lock/package-lock-2.json"
|
||||||
|
|||||||
54
syft/pkg/cataloger/javascript/testdata/pkg-lock/nested-package-lock-1.json
vendored
Normal file
54
syft/pkg/cataloger/javascript/testdata/pkg-lock/nested-package-lock-1.json
vendored
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
{
|
||||||
|
"requires": true,
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"dependencies": {
|
||||||
|
"parent": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/parent/-/parent-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-parent",
|
||||||
|
"dependencies": {
|
||||||
|
"shared": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/shared/-/shared-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-shared-1"
|
||||||
|
},
|
||||||
|
"middle": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/middle/-/middle-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-middle",
|
||||||
|
"dependencies": {
|
||||||
|
"shared": {
|
||||||
|
"version": "0.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/shared/-/shared-0.5.0.tgz",
|
||||||
|
"integrity": "sha512-shared-0.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"duplicate": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/duplicate/-/duplicate-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-duplicate"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"shared": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/shared/-/shared-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-shared-2"
|
||||||
|
},
|
||||||
|
"duplicate": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/duplicate/-/duplicate-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-duplicate"
|
||||||
|
},
|
||||||
|
"dev-parent": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"dev-nested": {
|
||||||
|
"version": "1.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user