Skip to content

Commit

Permalink
npm: package-lock license decoding to accept string or array (#1482)
Browse files Browse the repository at this point in the history
Signed-off-by: mikcl <mikesmikes400@gmail.com>
  • Loading branch information
Mikcl authored Jan 20, 2023
1 parent 972e4cd commit 396441e
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 7 deletions.
4 changes: 2 additions & 2 deletions syft/pkg/cataloger/javascript/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ func newPackageLockV1Package(resolver source.FileResolver, location source.Locat
func newPackageLockV2Package(resolver source.FileResolver, location source.Location, name string, u lockPackage) pkg.Package {
var licenses []string

if u.License != "" {
licenses = append(licenses, u.License)
if u.License != nil {
licenses = u.License
}

return finalizeLockPkg(
Expand Down
44 changes: 39 additions & 5 deletions syft/pkg/cataloger/javascript/parse_package_lock.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"io"
"strings"

"github.com/anchore/syft/internal/log"
"github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/pkg/cataloger/generic"
Expand All @@ -24,6 +25,39 @@ type packageLock struct {
Packages map[string]lockPackage
}

// packageLockLicense
type packageLockLicense []string

func (licenses *packageLockLicense) UnmarshalJSON(data []byte) (err error) {
// The license field could be either a string or an array.

// 1. An array
var arr []string
if err := json.Unmarshal(data, &arr); err == nil {
*licenses = arr
return nil
}

// 2. A string
var str string
if err = json.Unmarshal(data, &str); err == nil {
*licenses = make([]string, 1)
(*licenses)[0] = str
return nil
}

// debug the content we did not expect
if len(data) > 0 {
log.WithFields("license", string(data)).Debug("Unable to parse the following `license` value in package-lock.json")
}

// 3. Unexpected
// In case we are unable to parse the license field,
// i.e if we have not covered the full specification,
// we do not want to throw an error, instead assign nil.
return nil
}

// lockDependency represents a single package dependency listed in the package.lock json file
type lockDependency struct {
Version string `json:"version"`
Expand All @@ -32,11 +66,11 @@ type lockDependency struct {
}

type lockPackage struct {
Name string `json:"name"` // only present in the root package entry (named "")
Version string `json:"version"`
Resolved string `json:"resolved"`
Integrity string `json:"integrity"`
License string `json:"license"`
Name string `json:"name"` // only present in the root package entry (named "")
Version string `json:"version"`
Resolved string `json:"resolved"`
Integrity string `json:"integrity"`
License packageLockLicense `json:"license"`
}

// parsePackageLock parses a package-lock.json and returns the discovered JavaScript packages.
Expand Down
41 changes: 41 additions & 0 deletions syft/pkg/cataloger/javascript/parse_package_lock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,3 +297,44 @@ func TestParsePackageLockAlias(t *testing.T) {
pkgtest.TestFileParser(t, packageLock, parsePackageLock, expected, expectedRelationships)
}
}

func TestParsePackageLockLicenseWithArray(t *testing.T) {
fixture := "test-fixtures/pkg-lock/array-license-package-lock.json"
var expectedRelationships []artifact.Relationship
expectedPkgs := []pkg.Package{
{
Name: "tmp",
Version: "1.0.0",
Licenses: []string{"ISC"},
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
PURL: "pkg:npm/tmp@1.0.0",
MetadataType: "NpmPackageLockJsonMetadata",
Metadata: pkg.NpmPackageLockJSONMetadata{},
},
{
Name: "pause-stream",
Version: "0.0.11",
Licenses: []string{"MIT", "Apache2"},
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
PURL: "pkg:npm/pause-stream@0.0.11",
MetadataType: "NpmPackageLockJsonMetadata",
Metadata: pkg.NpmPackageLockJSONMetadata{},
},
{
Name: "through",
Version: "2.3.8",
Licenses: []string{"MIT"},
Language: pkg.JavaScript,
Type: pkg.NpmPkg,
PURL: "pkg:npm/through@2.3.8",
MetadataType: "NpmPackageLockJsonMetadata",
Metadata: pkg.NpmPackageLockJSONMetadata{},
},
}
for i := range expectedPkgs {
expectedPkgs[i].Locations.Add(source.NewLocation(fixture))
}
pkgtest.TestFileParser(t, fixture, parsePackageLock, expectedPkgs, expectedRelationships)
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 396441e

Please sign in to comment.