From 8cb78ce40ced6a731fb83f2a491a67444f541bf1 Mon Sep 17 00:00:00 2001 From: Rayan Salhab Date: Wed, 29 Apr 2026 16:50:09 +0300 Subject: [PATCH] fix: resolve yarn lock aliases to source package (#4836) Signed-off-by: cyphercodes --- syft/pkg/cataloger/javascript/parse_yarn_lock.go | 8 ++++++++ .../pkg/cataloger/javascript/parse_yarn_lock_test.go | 12 ++++++++++++ 2 files changed, 20 insertions(+) diff --git a/syft/pkg/cataloger/javascript/parse_yarn_lock.go b/syft/pkg/cataloger/javascript/parse_yarn_lock.go index af45f1407..7c849672a 100644 --- a/syft/pkg/cataloger/javascript/parse_yarn_lock.go +++ b/syft/pkg/cataloger/javascript/parse_yarn_lock.go @@ -25,6 +25,11 @@ import ( ) var ( + // packageAliasExp matches aliased yarn dependencies and captures the + // underlying npm package name instead of the local alias. + // For example: "old-async@npm:async@0.9.2" returns "async". + packageAliasExp = regexp.MustCompile(`^"?(?:@\w[\w-_.]*\/)?\w[\w-_.]*@npm:((?:@\w[\w-_.]*\/)?\w[\w-_.]*)@`) + // packageNameExp matches the name of the dependency in yarn.lock // including scope/namespace prefix if found. // For example: "aws-sdk@2.706.0" returns "aws-sdk" @@ -305,6 +310,9 @@ func (a genericYarnLockAdapter) parseYarnLock(ctx context.Context, resolver file } func findPackageName(line string) string { + if matches := packageAliasExp.FindStringSubmatch(line); len(matches) >= 2 { + return matches[1] + } if matches := packageNameExp.FindStringSubmatch(line); len(matches) >= 2 { return matches[1] } diff --git a/syft/pkg/cataloger/javascript/parse_yarn_lock_test.go b/syft/pkg/cataloger/javascript/parse_yarn_lock_test.go index cf308b194..06f675b31 100644 --- a/syft/pkg/cataloger/javascript/parse_yarn_lock_test.go +++ b/syft/pkg/cataloger/javascript/parse_yarn_lock_test.go @@ -708,6 +708,18 @@ func TestParseYarnFindPackageNames(t *testing.T) { line: `"color-convert@npm:^1.9.0":`, expected: "color-convert", }, + { + line: `"old-async@npm:async@0.9.2":`, + expected: "async", + }, + { + line: `"old-foo@npm:@scope/foo@1.2.3":`, + expected: "@scope/foo", + }, + { + line: `"@scope/old-foo@npm:@scope/foo@1.2.3":`, + expected: "@scope/foo", + }, { line: `"@npmcorp/code-frame@^7.1.0", "@npmcorp/code-frame@^7.10.4":`, expected: "@npmcorp/code-frame",