Skip to content

Commit

Permalink
feat: add support for licenses in package-lock json v2
Browse files Browse the repository at this point in the history
Signed-off-by: cpendery <[email protected]>
  • Loading branch information
cpendery committed Aug 17, 2022
1 parent 21eb772 commit 4033c39
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 58 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 @@ -76,7 +76,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
73 changes: 17 additions & 56 deletions syft/pkg/cataloger/javascript/parse_package_lock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,74 +30,36 @@ func assertPkgsEqual(t *testing.T, actual []*pkg.Package, expected map[string]pk

func TestParsePackageLock(t *testing.T) {
expected := map[string]pkg.Package{
"@actions/core": {
Name: "@actions/core",
Version: "1.6.0",
"@types/prop-types": {
Name: "@types/prop-types",
Version: "15.7.5",
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
Licenses: []string{"MIT"},
},
"wordwrap": {
Name: "wordwrap",
Version: "0.0.3",
"@types/react": {
Name: "@types/prop-types",
Version: "18.0.17",
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
Licenses: []string{"MIT"},
},
"get-stdin": {
Name: "get-stdin",
Version: "5.0.1",
"@types/scheduler": {
Name: "@types/scheduler",
Version: "0.16.2",
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
Licenses: []string{"MIT"},
},
"minimist": {
Name: "minimist",
Version: "0.0.10",
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
},
"optimist": {
Name: "optimist",
Version: "0.6.1",
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
},
"string-width": {
Name: "string-width",
Version: "2.1.1",
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
},
"strip-ansi": {
Name: "strip-ansi",
Version: "4.0.0",
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
},
"strip-eof": {
Name: "wordwrap",
Version: "1.0.0",
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
},
"ansi-regex": {
Name: "ansi-regex",
Version: "3.0.0",
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
},
"is-fullwidth-code-point": {
Name: "is-fullwidth-code-point",
Version: "2.0.0",
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
},
"cowsay": {
Name: "cowsay",
Version: "1.4.0",
"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.json")
fixture, err := os.Open("test-fixtures/pkg-lock/package-lock-2.json")
if err != nil {
t.Fatalf("failed to open fixture: %+v", err)
}
Expand All @@ -109,5 +71,4 @@ func TestParsePackageLock(t *testing.T) {
}

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 4033c39

Please sign in to comment.