fix(spdx): a package.json with no name drops every root-anchored edge and the DESCRIBES relationship
Nobody has claimed this yet.
- 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_OFrelationship at all - The document contains no
DESCRIBESrelationship and nodocumentDescribesfield - Sample of what is dropped:
@apollo/client,@babel/cli,@babel/eslint-parser. These are direct dependencies, so@apollo/clienthas 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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