feat(npm): handle aliases in package-lock.json (#1349)

This commit is contained in:
mikcl 2022-11-20 16:32:10 +00:00 committed by GitHub
parent da4b2df576
commit 04880c06ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 157 additions and 2 deletions

View File

@ -44,14 +44,29 @@ func newPackageJSONPackage(u packageJSON, locations ...source.Location) pkg.Pack
} }
func newPackageLockV1Package(resolver source.FileResolver, location source.Location, name string, u lockDependency) pkg.Package { func newPackageLockV1Package(resolver source.FileResolver, location source.Location, name string, u lockDependency) pkg.Package {
version := u.Version
const aliasPrefixPackageLockV1 = "npm:"
// Handles type aliases https://github.com/npm/rfcs/blob/main/implemented/0001-package-aliases.md
if strings.HasPrefix(version, aliasPrefixPackageLockV1) {
// this is an alias.
// `"version": "npm:canonical-name@X.Y.Z"`
canonicalPackageAndVersion := version[len(aliasPrefixPackageLockV1):]
versionSeparator := strings.LastIndex(canonicalPackageAndVersion, "@")
name = canonicalPackageAndVersion[:versionSeparator]
version = canonicalPackageAndVersion[versionSeparator+1:]
}
return finalizeLockPkg( return finalizeLockPkg(
resolver, resolver,
location, location,
pkg.Package{ pkg.Package{
Name: name, Name: name,
Version: u.Version, Version: version,
Locations: source.NewLocationSet(location), Locations: source.NewLocationSet(location),
PURL: packageURL(name, u.Version), PURL: packageURL(name, version),
Language: pkg.JavaScript, Language: pkg.JavaScript,
Type: pkg.NpmPkg, Type: pkg.NpmPkg,
}, },

View File

@ -75,6 +75,11 @@ func parsePackageLock(resolver source.FileResolver, _ *generic.Environment, read
} }
} }
// handles alias names
if pkgMeta.Name != "" {
name = pkgMeta.Name
}
pkgs = append(pkgs, newPackageLockV2Package(resolver, reader.Location, getNameFromPath(name), pkgMeta)) pkgs = append(pkgs, newPackageLockV2Package(resolver, reader.Location, getNameFromPath(name), pkgMeta))
} }
} }

View File

@ -193,3 +193,57 @@ func TestParsePackageLockV3(t *testing.T) {
} }
pkgtest.TestFileParser(t, fixture, parsePackageLock, expectedPkgs, expectedRelationships) pkgtest.TestFileParser(t, fixture, parsePackageLock, expectedPkgs, expectedRelationships)
} }
func TestParsePackageLockAlias(t *testing.T) {
var expectedRelationships []artifact.Relationship
commonPkgs := []pkg.Package{
{
Name: "case",
Version: "1.6.2",
PURL: "pkg:npm/case@1.6.2",
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
},
{
Name: "case",
Version: "1.6.3",
PURL: "pkg:npm/case@1.6.3",
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
},
{
Name: "@bundled-es-modules/chai",
Version: "4.2.2",
PURL: "pkg:npm/%40bundled-es-modules/chai@4.2.2",
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
},
}
v2Pkg := pkg.Package{
Name: "alias-check",
Version: "1.0.0",
PURL: "pkg:npm/alias-check@1.0.0",
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
Licenses: []string{"ISC"},
}
packageLockV1 := "test-fixtures/pkg-lock/alias-package-lock-1.json"
packageLockV2 := "test-fixtures/pkg-lock/alias-package-lock-2.json"
packageLocks := []string{packageLockV1, packageLockV2}
for _, packageLock := range packageLocks {
expected := make([]pkg.Package, len(commonPkgs))
copy(expected, commonPkgs)
if packageLock == packageLockV2 {
expected = append(expected, v2Pkg)
}
for i := range expected {
expected[i].Locations.Add(source.NewLocation(packageLock))
}
pkgtest.TestFileParser(t, packageLock, parsePackageLock, expected, expectedRelationships)
}
}

View File

@ -0,0 +1,23 @@
{
"name": "alias-check",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"case": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/case/-/case-1.6.2.tgz",
"integrity": "sha512-ll380ZRoraT7mUK2G92UbH+FJVD5AwdVIAYk9xhV1tauh0carDgYByUD1HhjCWsWgxrfQvCeHvtfj7IYR6TKeg=="
},
"case-alias": {
"version": "npm:case@1.6.3",
"resolved": "https://registry.npmjs.org/case/-/case-1.6.3.tgz",
"integrity": "sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ=="
},
"chai": {
"version": "npm:@bundled-es-modules/chai@4.2.2",
"resolved": "https://registry.npmjs.org/@bundled-es-modules/chai/-/chai-4.2.2.tgz",
"integrity": "sha512-iGmVYw2/zJCoqyKTtWEYCtFmMyi8WmACQKtky0lpNyEKWX0YIOpKWGD7saMXL+tPpllss0otilxV0SLwyi3Ytg=="
}
}
}

View File

@ -0,0 +1,58 @@
{
"name": "alias-check",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "alias-check",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"case": "1.6.2",
"case-alias": "npm:case@^1.6.3",
"chai": "npm:@bundled-es-modules/chai@^4.2.2"
}
},
"node_modules/case": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/case/-/case-1.6.2.tgz",
"integrity": "sha512-ll380ZRoraT7mUK2G92UbH+FJVD5AwdVIAYk9xhV1tauh0carDgYByUD1HhjCWsWgxrfQvCeHvtfj7IYR6TKeg==",
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/case-alias": {
"name": "case",
"version": "1.6.3",
"resolved": "https://registry.npmjs.org/case/-/case-1.6.3.tgz",
"integrity": "sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ==",
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/chai": {
"name": "@bundled-es-modules/chai",
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@bundled-es-modules/chai/-/chai-4.2.2.tgz",
"integrity": "sha512-iGmVYw2/zJCoqyKTtWEYCtFmMyi8WmACQKtky0lpNyEKWX0YIOpKWGD7saMXL+tPpllss0otilxV0SLwyi3Ytg=="
}
},
"dependencies": {
"case": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/case/-/case-1.6.2.tgz",
"integrity": "sha512-ll380ZRoraT7mUK2G92UbH+FJVD5AwdVIAYk9xhV1tauh0carDgYByUD1HhjCWsWgxrfQvCeHvtfj7IYR6TKeg=="
},
"case-alias": {
"version": "npm:case@1.6.3",
"resolved": "https://registry.npmjs.org/case/-/case-1.6.3.tgz",
"integrity": "sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ=="
},
"chai": {
"version": "npm:@bundled-es-modules/chai@4.2.2",
"resolved": "https://registry.npmjs.org/@bundled-es-modules/chai/-/chai-4.2.2.tgz",
"integrity": "sha512-iGmVYw2/zJCoqyKTtWEYCtFmMyi8WmACQKtky0lpNyEKWX0YIOpKWGD7saMXL+tPpllss0otilxV0SLwyi3Ytg=="
}
}
}