Skip to content

fix(sbom): resolve Yarn dependency edges from the lockfile graph #1109

Description

@sonukapoor

Note: this is an in-house item already being handled by the maintainer - not open for contribution. Filed for tracking only.

Follow-up to #1079, which fixed SBOM dependency-graph completeness for npm only. Sibling of #1107 (pnpm) and #1108 (Bun).

Do this one last. It is the largest of the three and carries most of the risk. The estimate below is the least reliable of the set.

Problem

Yarn still derives SBOM dependency edges by prefix-matching PackageRef.paths, capped at MAX_PATHS_PER_PACKAGE = 5 (src/parsers/yarn-lock.ts:8). Same consequence as #1107 and #1108: lost edges on large trees, orphaned packages when the surviving routes traverse excluded packages, and a weaker answer on the NTIA dependency-relationship element.

Why this is harder than the other two

Two incompatible lockfile formats. yarn-lock.ts detects Berry via __metadata (line 158, and again at 309 and 335). Classic v1 and Berry differ enough that edge extraction likely needs separate handling for each.

Classic keys entries by range, not by version. A v1 lockfile keys entries as name@range, so building name@version edges means resolving ranges to the concrete versions actually installed. That is real work, not plumbing, and it is the main reason this is a one-to-two day job rather than half a day.

No existing children map to reuse. Unlike pnpm (which has graph at pnpm-lock.ts:108) and Bun (childDepsByPackageName), the Yarn parser has its own bespoke path-recording logic at line 200 and does not build a reusable adjacency structure. This one is built from scratch.

Important: do not record edges during the path traversal

yarn-lock.ts:35 and :200 both cap while walking, so edges recorded there inherit the incompleteness. Separate edge-only pass, as with the others.

Scope

  • Build a child-to-parents edge map keyed by name@version, covering both classic and Berry.
  • Extend resolveDependencyEdges (src/output/sbom-dependency-edges.ts) for yarn-lock.
  • Handle workspace members (linked, no version) and parents filtered out of the scanned set by anchoring to the root rather than orphaning. Never emit a reference to a package absent from the document.
  • Update website/docs/spdx.md, which currently lists Yarn among the affected ecosystems. Once this lands, that per-package-manager split can be removed entirely.

Keep MAX_PATHS_PER_PACKAGE at 5.

Verification

examples/yarn-berry for Berry and examples/twenty for classic. Both formats need checking; a fix verified on only one is not done. Confirm packages with no parent edge drop to the root project alone, and zero dangling references.

Estimate

One to two days, and less certain than the other two. I have read the parser but not traced the range-resolution path in detail, so if that turns out to need more than a lookup against already-resolved entries, this grows. Re-estimate after an hour of reading rather than committing to the number up front.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingin-houseMaintainer-handled internal work - not open for contribution

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions