mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-06 04:41:18 -08:00
feat(nodejs): add yarn alias support (#5818)
Signed-off-by: knqyf263 <knqyf263@gmail.com> Co-authored-by: knqyf263 <knqyf263@gmail.com>
This commit is contained in:
@@ -42,7 +42,10 @@ By default, Trivy doesn't report development dependencies. Use the `--include-de
|
||||
|
||||
### Yarn
|
||||
Trivy parses `yarn.lock`, which doesn't contain information about development dependencies.
|
||||
To exclude devDependencies, `package.json` also needs to be present next to `yarn.lock`.
|
||||
Trivy also uses `package.json` file to handle [aliases](https://classic.yarnpkg.com/lang/en/docs/cli/add/#toc-yarn-add-alias).
|
||||
|
||||
To exclude devDependencies and allow aliases, `package.json` also needs to be present next to `yarn.lock`.
|
||||
|
||||
Trivy analyzes `.yarn` (Yarn 2+) or `node_modules` (Yarn Classic) folder next to the yarn.lock file to detect licenses.
|
||||
|
||||
By default, Trivy doesn't report development dependencies. Use the `--include-dev-deps` flag to include them.
|
||||
|
||||
14
pkg/fanal/analyzer/language/nodejs/yarn/testdata/alias/package.json
vendored
Normal file
14
pkg/fanal/analyzer/language/nodejs/yarn/testdata/alias/package.json
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "test",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"foo-json": "npm:@types/jsonstream@0.8.33",
|
||||
"foo-uuid": "npm:@types/uuid"
|
||||
},
|
||||
"dependencies": {
|
||||
"foo-debug": "npm:debug@^4.3",
|
||||
"foo-ms": "npm:ms"
|
||||
}
|
||||
}
|
||||
44
pkg/fanal/analyzer/language/nodejs/yarn/testdata/alias/yarn.lock
vendored
Normal file
44
pkg/fanal/analyzer/language/nodejs/yarn/testdata/alias/yarn.lock
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@types/node@*":
|
||||
version "20.10.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.5.tgz#47ad460b514096b7ed63a1dae26fad0914ed3ab2"
|
||||
integrity sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==
|
||||
dependencies:
|
||||
undici-types "~5.26.4"
|
||||
|
||||
"foo-debug@npm:debug@^4.3":
|
||||
version "4.3.4"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
|
||||
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
"foo-json@npm:@types/jsonstream@0.8.33":
|
||||
version "0.8.33"
|
||||
resolved "https://registry.yarnpkg.com/@types/jsonstream/-/jsonstream-0.8.33.tgz#7d37a16a78cf68a67858110dc1767023436fca23"
|
||||
integrity sha512-yhg1SNOgJ8y2nOkvAQ1zZ1Z2xibxgFs7984+EeBPuWgo/TbuYo79+rj2wUVch3KF4GhhcwAi/AlJcehmLCXb3g==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"foo-ms@npm:ms":
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||
|
||||
"foo-uuid@npm:@types/uuid":
|
||||
version "9.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.7.tgz#b14cebc75455eeeb160d5fe23c2fcc0c64f724d8"
|
||||
integrity sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==
|
||||
|
||||
ms@2.1.2:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
|
||||
undici-types@~5.26.4:
|
||||
version "5.26.5"
|
||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
|
||||
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
@@ -36,6 +37,10 @@ func init() {
|
||||
|
||||
const version = 2
|
||||
|
||||
// Taken from Yarn
|
||||
// cf. https://github.com/yarnpkg/yarn/blob/328fd596de935acc6c3e134741748fcc62ec3739/src/resolvers/exotics/registry-resolver.js#L12
|
||||
var fragmentRegexp = regexp.MustCompile(`(\S+):(@?.*?)(@(.*?)|)$`)
|
||||
|
||||
type yarnAnalyzer struct {
|
||||
packageJsonParser *packagejson.Parser
|
||||
lockParser godeptypes.Parser
|
||||
@@ -193,17 +198,30 @@ func (a yarnAnalyzer) walkDependencies(libs []types.Package, pkgIDs map[string]t
|
||||
// Identify direct dependencies
|
||||
pkgs := make(map[string]types.Package)
|
||||
for _, pkg := range libs {
|
||||
if constraint, ok := directDeps[pkg.Name]; ok {
|
||||
// npm has own comparer to compare versions
|
||||
if match, err := a.comparer.MatchVersion(pkg.Version, constraint); err != nil {
|
||||
return nil, xerrors.Errorf("unable to match version for %s", pkg.Name)
|
||||
} else if match {
|
||||
// Mark as a direct dependency
|
||||
pkg.Indirect = false
|
||||
pkg.Dev = dev
|
||||
pkgs[pkg.ID] = pkg
|
||||
}
|
||||
constraint, ok := directDeps[pkg.Name]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// Handle aliases
|
||||
// cf. https://classic.yarnpkg.com/lang/en/docs/cli/add/#toc-yarn-add-alias
|
||||
if m := fragmentRegexp.FindStringSubmatch(constraint); len(m) == 5 {
|
||||
pkg.Name = m[2] // original name
|
||||
constraint = m[4]
|
||||
}
|
||||
|
||||
// npm has own comparer to compare versions
|
||||
if match, err := a.comparer.MatchVersion(pkg.Version, constraint); err != nil {
|
||||
return nil, xerrors.Errorf("unable to match version for %s", pkg.Name)
|
||||
} else if !match {
|
||||
continue
|
||||
}
|
||||
|
||||
// Mark as a direct dependency
|
||||
pkg.Indirect = false
|
||||
pkg.Dev = dev
|
||||
pkgs[pkg.ID] = pkg
|
||||
|
||||
}
|
||||
|
||||
// Walk indirect dependencies
|
||||
|
||||
@@ -318,6 +318,117 @@ func Test_yarnLibraryAnalyzer_Analyze(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "happy path with alias rewrite",
|
||||
dir: "testdata/alias",
|
||||
want: &analyzer.AnalysisResult{
|
||||
Applications: []types.Application{
|
||||
{
|
||||
Type: types.Yarn,
|
||||
FilePath: "yarn.lock",
|
||||
Libraries: types.Packages{
|
||||
{
|
||||
ID: "foo-json@0.8.33",
|
||||
Name: "@types/jsonstream",
|
||||
Version: "0.8.33",
|
||||
Indirect: false,
|
||||
Dev: true,
|
||||
Locations: []types.Location{
|
||||
{
|
||||
StartLine: 19,
|
||||
EndLine: 24,
|
||||
},
|
||||
},
|
||||
DependsOn: []string{
|
||||
"@types/node@20.10.5",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "@types/node@20.10.5",
|
||||
Name: "@types/node",
|
||||
Version: "20.10.5",
|
||||
Indirect: true,
|
||||
Dev: true,
|
||||
Locations: []types.Location{
|
||||
{
|
||||
StartLine: 5,
|
||||
EndLine: 10,
|
||||
},
|
||||
},
|
||||
DependsOn: []string{
|
||||
"undici-types@5.26.5",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "foo-uuid@9.0.7",
|
||||
Name: "@types/uuid",
|
||||
Version: "9.0.7",
|
||||
Indirect: false,
|
||||
Dev: true,
|
||||
Locations: []types.Location{
|
||||
{
|
||||
StartLine: 31,
|
||||
EndLine: 34,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "foo-debug@4.3.4",
|
||||
Name: "debug",
|
||||
Version: "4.3.4",
|
||||
Indirect: false,
|
||||
Locations: []types.Location{
|
||||
{
|
||||
StartLine: 12,
|
||||
EndLine: 17,
|
||||
},
|
||||
},
|
||||
DependsOn: []string{
|
||||
"ms@2.1.2",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "ms@2.1.2",
|
||||
Name: "ms",
|
||||
Version: "2.1.2",
|
||||
Indirect: true,
|
||||
Locations: []types.Location{
|
||||
{
|
||||
StartLine: 36,
|
||||
EndLine: 39,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "foo-ms@2.1.3",
|
||||
Name: "ms",
|
||||
Version: "2.1.3",
|
||||
Indirect: false,
|
||||
Locations: []types.Location{
|
||||
{
|
||||
StartLine: 26,
|
||||
EndLine: 29,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "undici-types@5.26.5",
|
||||
Name: "undici-types",
|
||||
Version: "5.26.5",
|
||||
Indirect: true,
|
||||
Dev: true,
|
||||
Locations: []types.Location{
|
||||
{
|
||||
StartLine: 41,
|
||||
EndLine: 44,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "monorepo",
|
||||
dir: "testdata/monorepo",
|
||||
|
||||
Reference in New Issue
Block a user