Skip to content

Commit

Permalink
feat(parser): save depPaths with non-default registries to ExternalRef
Browse files Browse the repository at this point in the history
  • Loading branch information
DmitriyLewen committed May 21, 2024
1 parent ef73ee6 commit 2d50522
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 34 deletions.
70 changes: 45 additions & 25 deletions pkg/dependency/parser/nodejs/pnpm/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,10 @@ func (p *Parser) parse(lockVer float64, lockFile LockFile) ([]ftypes.Package, []
// cf. https://github.com/pnpm/spec/blob/274ff02de23376ad59773a9f25ecfedd03a41f64/lockfile/6.0.md#packagesdependencypathname
name := info.Name
version := info.Version
var ref string

if name == "" {
name, version = p.parseDepPath(depPath, lockVer)
name, version, ref = p.parseDepPath(depPath, lockVer)
version = p.parseVersion(depPath, version, lockVer)
}
pkgID := packageID(name, version)
Expand All @@ -123,10 +124,11 @@ func (p *Parser) parse(lockVer float64, lockFile LockFile) ([]ftypes.Package, []
}

pkgs = append(pkgs, ftypes.Package{
ID: pkgID,
Name: name,
Version: version,
Relationship: lo.Ternary(isDirectPkg(name, lockFile.Dependencies), ftypes.RelationshipDirect, ftypes.RelationshipIndirect),
ID: pkgID,
Name: name,
Version: version,
Relationship: lo.Ternary(isDirectPkg(name, lockFile.Dependencies), ftypes.RelationshipDirect, ftypes.RelationshipIndirect),
ExternalReferences: toExternalRefs(ref),
})

if len(dependencies) > 0 {
Expand All @@ -149,7 +151,7 @@ func (p *Parser) parseV9(lockFile LockFile) ([]ftypes.Package, []ftypes.Dependen
// Check all snapshots and save with resolved versions
resolvedSnapshots := make(map[string][]string)
for depPath, snapshot := range lockFile.Snapshots {
name, version := p.parseDepPath(depPath, lockVer)
name, version, _ := p.parseDepPath(depPath, lockVer)

var dependsOn []string
for depName, depVer := range lo.Assign(snapshot.OptionalDependencies, snapshot.Dependencies) {
Expand All @@ -167,7 +169,7 @@ func (p *Parser) parseV9(lockFile LockFile) ([]ftypes.Package, []ftypes.Dependen
}

for depPath, pkgInfo := range lockFile.Packages {
name, ver := p.parseDepPath(depPath, lockVer)
name, ver, ref := p.parseDepPath(depPath, lockVer)
parsedVer := p.parseVersion(depPath, ver, lockVer)

if pkgInfo.Version != "" {
Expand All @@ -188,11 +190,12 @@ func (p *Parser) parseV9(lockFile LockFile) ([]ftypes.Package, []ftypes.Dependen

id := packageID(name, parsedVer)
resolvedPkgs[id] = ftypes.Package{
ID: id,
Name: name,
Version: parsedVer,
Relationship: relationship,
Dev: dev,
ID: id,
Name: name,
Version: parsedVer,
Relationship: relationship,
Dev: dev,
ExternalReferences: toExternalRefs(ref),
}

// Save child deps
Expand Down Expand Up @@ -252,8 +255,8 @@ func (p *Parser) parseLockfileVersion(lockFile LockFile) float64 {
}
}

func (p *Parser) parseDepPath(depPath string, lockVer float64) (string, string) {
dPath := p.trimDefaultRegistry(depPath, lockVer)
func (p *Parser) parseDepPath(depPath string, lockVer float64) (string, string, string) {
dPath, nonDefaultRegistry := p.trimRegistry(depPath, lockVer)

var scope string
scope, dPath = p.separateScope(dPath)
Expand All @@ -268,23 +271,28 @@ func (p *Parser) parseDepPath(depPath string, lockVer float64) (string, string)

ver := p.trimPeerDeps(dPath, lockVer)

return name, ver
return name, ver, lo.Ternary(nonDefaultRegistry, depPath, "")
}

// trimDefaultRegistry trims default (`registry.npmjs.org`) registry (or `/` prefix) for depPath.
// trimRegistry trims registry (or `/` prefix) for depPath.
// It returns true if non-default registry has been trimmed.
// e.g.
// - "registry.npmjs.org/lodash/4.17.10" => "lodash/4.17.10"
// - "registry.npmjs.org/@babel/generator/7.21.9" => "@babel/generator/7.21.9"
// - "/lodash/4.17.10" => "lodash/4.17.10"
// - "/asap@2.0.6" => "asap@2.0.6"
// - "private.npm.org/@babel/generator/7.21.9" => "private.npm.org/@babel/generator/7.21.9"
func (p *Parser) trimDefaultRegistry(depPath string, lockVer float64) string {
// - "registry.npmjs.org/lodash/4.17.10" => "lodash/4.17.10", false
// - "registry.npmjs.org/@babel/generator/7.21.9" => "@babel/generator/7.21.9", false
// - "private.npm.org/@babel/generator/7.21.9" => "@babel/generator/7.21.9", true
// - "/lodash/4.17.10" => "lodash/4.17.10", false
// - "/asap@2.0.6" => "asap@2.0.6", false
func (p *Parser) trimRegistry(depPath string, lockVer float64) (string, bool) {
var nonDefaultRegistry bool
// lock file v9 doesn't use registry prefix
if lockVer < 9 {
depPath = strings.TrimPrefix(depPath, "registry.npmjs.org")
depPath = strings.TrimPrefix(depPath, "/")
var registry string
registry, depPath, _ = strings.Cut(depPath, "/")
if registry != "" && registry != "registry.npmjs.org" {
nonDefaultRegistry = true
}
}
return depPath
return depPath, nonDefaultRegistry
}

// separateScope separates the scope (if set) from the rest of the depPath.
Expand Down Expand Up @@ -360,3 +368,15 @@ func isDirectPkg(name string, directDeps map[string]interface{}) bool {
func packageID(name, version string) string {
return dependency.ID(ftypes.Pnpm, name, version)
}

func toExternalRefs(ref string) []ftypes.ExternalRef {
if ref == "" {
return nil
}
return []ftypes.ExternalRef{
{
Type: ftypes.RefVCS,
URL: ref,
},
}
}
34 changes: 25 additions & 9 deletions pkg/dependency/parser/nodejs/pnpm/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ import (
"sort"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
"github.com/stretchr/testify/require"
)

func TestParse(t *testing.T) {
Expand Down Expand Up @@ -72,7 +70,7 @@ func TestParse(t *testing.T) {

sort.Sort(ftypes.Packages(got))
sort.Sort(ftypes.Packages(tt.want))
assert.Equal(t, tt.want, got)
require.Equal(t, tt.want, got)

if tt.wantDeps != nil {
sort.Sort(ftypes.Dependencies(deps))
Expand All @@ -83,7 +81,7 @@ func TestParse(t *testing.T) {
for _, dep := range tt.wantDeps {
sort.Strings(dep.DependsOn)
}
assert.Equal(t, tt.wantDeps, deps)
require.Equal(t, tt.wantDeps, deps)
}
})
}
Expand All @@ -96,6 +94,7 @@ func Test_parseDepPath(t *testing.T) {
pkg string
wantName string
wantVersion string
wantRef string
}{
{
name: "v5 - relative path",
Expand All @@ -111,6 +110,14 @@ func Test_parseDepPath(t *testing.T) {
wantName: "lodash",
wantVersion: "4.17.10",
},
{
name: "v5 - non-default registry",
lockFileVer: 5.0,
pkg: "private.npmjs.org/lodash/4.17.10",
wantName: "lodash",
wantVersion: "4.17.10",
wantRef: "private.npmjs.org/lodash/4.17.10",
},
{
name: "v5 - relative path with slash",
lockFileVer: 5.0,
Expand Down Expand Up @@ -160,6 +167,14 @@ func Test_parseDepPath(t *testing.T) {
wantName: "lodash",
wantVersion: "4.17.10",
},
{
name: "v6 - non-default registry",
lockFileVer: 6.0,
pkg: "private.npmjs.org/lodash@4.17.10",
wantName: "lodash",
wantVersion: "4.17.10",
wantRef: "private.npmjs.org/lodash@4.17.10",
},
{
name: "v6 - relative path with slash",
lockFileVer: 6.0,
Expand Down Expand Up @@ -207,9 +222,10 @@ func Test_parseDepPath(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := NewParser()
gotName, gotVersion := p.parseDepPath(tt.pkg, tt.lockFileVer)
assert.Equal(t, tt.wantName, gotName)
assert.Equal(t, tt.wantVersion, gotVersion)
gotName, gotVersion, gotRef := p.parseDepPath(tt.pkg, tt.lockFileVer)
require.Equal(t, tt.wantName, gotName)
require.Equal(t, tt.wantVersion, gotVersion)
require.Equal(t, tt.wantRef, gotRef)
})

}
Expand Down Expand Up @@ -258,7 +274,7 @@ func Test_parseVersion(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
p := NewParser()
gotVer := p.parseVersion("depPath", tt.ver, tt.lockVer)
assert.Equal(t, tt.wantVer, gotVer)
require.Equal(t, tt.wantVer, gotVer)
})

}
Expand Down

0 comments on commit 2d50522

Please sign in to comment.