Skip to content

Commit

Permalink
feat: add support for licenses in package-lock json v2 (#1164)
Browse files Browse the repository at this point in the history
  • Loading branch information
cpendery authored Aug 22, 2022
1 parent 1329688 commit c56d3b5
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 2 deletions.
2 changes: 1 addition & 1 deletion syft/pkg/cataloger/javascript/cataloger.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func addLicenses(resolver source.FileResolver, location source.Location, p *pkg.
return nil
}

p.Licenses = licenses
p.Licenses = append(p.Licenses, licenses...)
}

return nil
Expand Down
26 changes: 25 additions & 1 deletion syft/pkg/cataloger/javascript/parse_package_lock.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"io"
"strings"

"github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/pkg"
Expand All @@ -18,14 +19,21 @@ type PackageLock struct {
Requires bool `json:"requires"`
LockfileVersion int `json:"lockfileVersion"`
Dependencies map[string]Dependency
Packages map[string]Package
}

// Dependency represents a single package dependency listed in the package.lock json file
type Dependency struct {
Version string `json:"version"`
Resolved string `json:"resolved"`
Integrity string `json:"integrity"`
Requires map[string]string
}

type Package struct {
Version string `json:"version"`
Resolved string `json:"resolved"`
Integrity string `json:"integrity"`
License string `json:""`
}

// parsePackageLock parses a package-lock.json and returns the discovered JavaScript packages.
Expand All @@ -46,12 +54,28 @@ func parsePackageLock(path string, reader io.Reader) ([]*pkg.Package, []artifact
} else if err != nil {
return nil, nil, fmt.Errorf("failed to parse package-lock.json file: %w", err)
}
licenseMap := make(map[string]string)
for _, pkgMeta := range lock.Packages {
var sb strings.Builder
sb.WriteString(pkgMeta.Resolved)
sb.WriteString(pkgMeta.Integrity)
licenseMap[sb.String()] = pkgMeta.License
}

for name, pkgMeta := range lock.Dependencies {
var sb strings.Builder
sb.WriteString(pkgMeta.Resolved)
sb.WriteString(pkgMeta.Integrity)
var licenses []string
if license, exists := licenseMap[sb.String()]; exists {
licenses = append(licenses, license)
}
packages = append(packages, &pkg.Package{
Name: name,
Version: pkgMeta.Version,
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
Licenses: licenses,
})
}
}
Expand Down
44 changes: 44 additions & 0 deletions syft/pkg/cataloger/javascript/parse_package_lock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,47 @@ func TestParsePackageLock(t *testing.T) {
assertPkgsEqual(t, actual, expected)

}

func TestParsePackageLockV2(t *testing.T) {
expected := map[string]pkg.Package{
"@types/prop-types": {
Name: "@types/prop-types",
Version: "15.7.5",
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
Licenses: []string{"MIT"},
},
"@types/react": {
Name: "@types/prop-types",
Version: "18.0.17",
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
Licenses: []string{"MIT"},
},
"@types/scheduler": {
Name: "@types/scheduler",
Version: "0.16.2",
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
Licenses: []string{"MIT"},
},
"csstype": {
Name: "csstype",
Version: "3.1.0",
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
Licenses: []string{"MIT"},
},
}
fixture, err := os.Open("test-fixtures/pkg-lock/package-lock-2.json")
if err != nil {
t.Fatalf("failed to open fixture: %+v", err)
}

actual, _, err := parsePackageLock(fixture.Name(), fixture)
if err != nil {
t.Fatalf("failed to parse package-lock.json: %+v", err)
}

assertPkgsEqual(t, actual, expected)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{
"name": "npm",
"version": "6.14.6",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "npm",
"version": "6.14.6",
"dependencies": {
"@types/react": "^18.0.9"
}
},
"node_modules/@types/prop-types": {
"version": "15.7.5",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
"integrity": "sha1-XxnSuFqY6VWANvajysyIGUIPBc8=",
"license": "MIT"
},
"node_modules/@types/react": {
"version": "18.0.17",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.17.tgz",
"integrity": "sha1-RYPZwyLWfv5LOak10iPtzHBQzPQ=",
"license": "MIT",
"dependencies": {
"@types/prop-types": "*",
"@types/scheduler": "*",
"csstype": "^3.0.2"
}
},
"node_modules/@types/scheduler": {
"version": "0.16.2",
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
"integrity": "sha1-GmL4lSVyPd4kuhsBsJK/XfitTTk=",
"license": "MIT"
},
"node_modules/csstype": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
"integrity": "sha1-TdysNxjXh8+d8NG30VAzklyPKfI=",
"license": "MIT"
}
},
"dependencies": {
"@types/prop-types": {
"version": "15.7.5",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
"integrity": "sha1-XxnSuFqY6VWANvajysyIGUIPBc8="
},
"@types/react": {
"version": "18.0.17",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.17.tgz",
"integrity": "sha1-RYPZwyLWfv5LOak10iPtzHBQzPQ=",
"requires": {
"@types/prop-types": "*",
"@types/scheduler": "*",
"csstype": "^3.0.2"
}
},
"@types/scheduler": {
"version": "0.16.2",
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz",
"integrity": "sha1-GmL4lSVyPd4kuhsBsJK/XfitTTk="
},
"csstype": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz",
"integrity": "sha1-TdysNxjXh8+d8NG30VAzklyPKfI="
}
}
}

0 comments on commit c56d3b5

Please sign in to comment.