Safeguard
Security Guides•

What does the SPDX DESCRIBES relationship do and when is it needed?

DESCRIBES links the SPDX document to the package it covers, and is mandatory when more than one package is present. How to write it and avoid mistakes.

Safeguard Security Team
4 min read

In SPDX 2.3, the DESCRIBES relationship connects the document itself to the package or files it is about. The spec calls it a logical relationship that is mandatory when more than one package or set of files is present. It tells a reader which element is the top of the tree, so everything else makes sense.

What the spec says

SPDX 2.3.1 defines DESCRIBES for use when SPDXRef-DOCUMENT describes another element. Its example is a document WildFly.spdx describing the package WildFly. The spec notes this is a logical relationship that helps organize related items within a document, and that it is mandatory if more than one package or set of files, not in a package, is present. The reverse, DESCRIBED_BY, states the same thing from the other side.

SPDXID: SPDXRef-DOCUMENT
Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-Package-myapp
Relationship: SPDXRef-Package-myapp DEPENDS_ON SPDXRef-Package-lodash

Why it matters

Without it, a document with fifty packages looks like fifty equal items. A reader cannot tell which one is your product and which are things it uses. Tools that compute what you ship, or that walk the tree for a vulnerability search, need an entry point.

In CycloneDX, the same job is done by the root component in the metadata section. If you convert between formats, make sure the root survives. An SPDX file with no DESCRIBES and a CycloneDX file with no metadata component both lose their entry point.

How to use it well

CaseWhat to write
One applicationDESCRIBES the application package, which then has DEPENDS_ON edges
A container imageDESCRIBES the image package, with CONTAINS or DEPENDS_ON for what is inside
Several deliverables in one fileDESCRIBES each, one line per deliverable
A library with no consumerDESCRIBES the library itself

Make the described package the one your customer would name. If you ship a product called Atlas, DESCRIBES should point at Atlas, not at an internal build package.

Common mistakes

No DESCRIBES in a multi-package file. This breaks the mandatory rule from the spec.

Describing everything. If the document DESCRIBES every dependency, the root is lost again. Use DESCRIBES for what the document is about, and DEPENDS_ON for the rest.

Pointing at a missing identifier. The target SPDXID must exist in the same document.

Reversed direction. DESCRIBED_BY with the arguments swapped produces the opposite claim.

A quick check

Search the file for DESCRIBES. You should find at least one, and the target should be your product. Follow the DEPENDS_ON edges from it, and confirm that the packages you expect appear within a few hops. If large groups of packages cannot be reached from the root, the graph is incomplete or disconnected, and any impact search will miss them.

Safeguard can generate SBOMs and run dependency scanning across your repositories, so the fields discussed here are checked on real projects instead of by hand. You can try the free scan at gold.safeguard.sh/scan.

Try it yourself

Open the demo, click through the component list, and look at how each package is identified and what is missing.

Click through it at your own pace, or open it full screen.

Quick check

Is DESCRIBES always required?

The spec says it is mandatory if more than one package or set of files not in a package is present.

What is the CycloneDX equivalent?

The root component in metadata plays a similar role, naming what the BOM is about.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.