diff --git a/syft/pkg/cataloger/javascript/parse_package_json.go b/syft/pkg/cataloger/javascript/parse_package_json.go index d80781d6fb4..4a105d515fa 100644 --- a/syft/pkg/cataloger/javascript/parse_package_json.go +++ b/syft/pkg/cataloger/javascript/parse_package_json.go @@ -27,7 +27,7 @@ type packageJSON struct { Latest []string `json:"latest"` Author author `json:"author"` License json.RawMessage `json:"license"` - Licenses []license `json:"licenses"` + Licenses json.RawMessage `json:"licenses"` Name string `json:"name"` Homepage string `json:"homepage"` Description string `json:"description"` @@ -145,8 +145,10 @@ func (p packageJSON) licensesFromJSON() ([]string, error) { return []string{singleLicense}, nil } + multiLicense, err := licensesFromJSON(p.Licenses) + // The "licenses" field is deprecated. It should be inspected as a last resort. - if p.Licenses != nil { + if multiLicense != nil && err == nil { mapLicenses := func(licenses []license) []string { mappedLicenses := make([]string, len(licenses)) for i, l := range licenses { @@ -155,10 +157,20 @@ func (p packageJSON) licensesFromJSON() ([]string, error) { return mappedLicenses } - return mapLicenses(p.Licenses), nil + return mapLicenses(multiLicense), nil + } + + return nil, err +} + +func licensesFromJSON(b []byte) ([]license, error) { + var licenseObject []license + err := json.Unmarshal(b, &licenseObject) + if err == nil { + return licenseObject, nil } - return nil, fmt.Errorf("unable to parse license field: %w", err) + return nil, errors.New("unmarshal failed") } // parsePackageJSON parses a package.json and returns the discovered JavaScript packages. diff --git a/syft/pkg/cataloger/javascript/parse_package_json_test.go b/syft/pkg/cataloger/javascript/parse_package_json_test.go index 2c9d6ea07ab..427a50f61a7 100644 --- a/syft/pkg/cataloger/javascript/parse_package_json_test.go +++ b/syft/pkg/cataloger/javascript/parse_package_json_test.go @@ -71,6 +71,25 @@ func TestParsePackageJSON(t *testing.T) { }, }, }, + { + Fixture: "test-fixtures/pkg-json/package-malformed-license.json", + ExpectedPkg: pkg.Package{ + Name: "npm", + Version: "6.14.6", + Type: pkg.NpmPkg, + Licenses: nil, + Language: pkg.JavaScript, + MetadataType: pkg.NpmPackageJSONMetadataType, + Metadata: pkg.NpmPackageJSONMetadata{ + Name: "npm", + Version: "6.14.6", + Author: "Isaac Z. Schlueter (http://blog.izs.me)", + Homepage: "https://docs.npmjs.com/", + URL: "https://github.com/npm/cli", + Licenses: nil, + }, + }, + }, { Fixture: "test-fixtures/pkg-json/package-no-license.json", ExpectedPkg: pkg.Package{ diff --git a/syft/pkg/cataloger/javascript/test-fixtures/pkg-json/package-malformed-license.json b/syft/pkg/cataloger/javascript/test-fixtures/pkg-json/package-malformed-license.json new file mode 100644 index 00000000000..3ddba4d85c3 --- /dev/null +++ b/syft/pkg/cataloger/javascript/test-fixtures/pkg-json/package-malformed-license.json @@ -0,0 +1,19 @@ +{ + "version": "6.14.6", + "name": "npm", + "description": "a package manager for JavaScript", + "homepage": "https://docs.npmjs.com/", + "author": "Isaac Z. Schlueter (http://blog.izs.me)", + "repository": { + "type": "git", + "url": "https://github.com/npm/cli" + }, + "bugs": { + "url": "https://npm.community/c/bugs" + }, + "main": "./lib/npm.js", + "licenses": [ "MIT" ], + "engines": { + "node": "6 >=6.2.0 || 8 || >=9.3.0" + } +}