OWASP / OWASP/cve-lite-cli

fix(spdx): a package.json with no name drops every root-anchored edge and the DESCRIBES relationship

Open
#1,134 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug in-house
Dominant language
TypeScript
Stars
715
Forks
145
Avg merge
21h 39m
Merged PRs (30d)
66

Description

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

Found while verifying #1132. A project whose package.json has no name field silently loses every root-anchored dependency edge from its SPDX document, and loses the DESCRIBES relationship as well.

Mechanism

buildRootPackage (src/output/spdx.ts:168) returns null when !projectMeta?.name, so no root package is emitted and rootId is null. The edge loop then does:

const parentId = parent === null ? rootId : idByPackage.get(parent);
if (!parentId || parentId === childId) continue;

resolveDependencyEdges emits parent: null for every package that nothing else depends on, which is exactly the direct dependencies. With rootId null, all of those are dropped.

Measured

examples/gatsby, whose package.json has no name:

  • 380 of 3568 packages have no outgoing DEPENDENCY_OF relationship at all
  • The document contains no DESCRIBES relationship and no documentDescribes field
  • Sample of what is dropped: @apollo/client, @babel/cli, @babel/eslint-parser. These are direct dependencies, so @apollo/client has 13 packages depending on it but is itself attached to nothing

Control, examples/analog, which does have a name: 1 package with no outgoing edge, that being the root project, and DESCRIBES present.

Why it matters more than the count suggests

Dependency relationships are an NTIA minimum element, which is the whole premise of the SBOM work in #1106, #1107, #1108 and #1109. An SPDX document with no DESCRIBES is also arguably not a valid document, since SPDX expects the document to describe something.

It is also silent. Nothing warns, and the package list is complete, so the SBOM looks fine.

Not package-manager specific

The drop happens in the SPDX renderer, downstream of edge resolution, so npm, pnpm, Yarn and Bun are all affected identically. examples/gatsby is Yarn only because that is where it was noticed.

Fix direction

Synthesise a root when the manifest has no name, rather than omitting it. The directory name is a reasonable fallback, and SPDX allows NOASSERTION for fields that cannot be determined. Failing that, warn rather than dropping edges silently.

A caveat is documented in website/docs/spdx.md as of #1132, but documenting it is not the fix.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/output/spdx.ts at buildRootPackage and trace how rootId is used by the dependency-edge loop and DESCRIBES relationship generation. Compare the SPDX output for examples/gatsby and examples/analog. Done means unnamed manifests retain their root-anchored dependency relationships and document description without silently dropping edges.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.