Safeguard
Security Guides•

What are omniborId and swhid in a CycloneDX component?

Both are content-based identifiers for a component, alongside purl and cpe. What each one is, what the 1.6 schema says, and when adding them is worth it.

Safeguard Security Team
3 min read

omniborId and swhid are two extra identity fields on a CycloneDX 1.6 component. Each holds a content-derived identifier, an OmniBOR artifact ID or a Software Heritage persistent identifier, and both are arrays. Most projects can leave them out and rely on purl, but they help when names and versions are unreliable.

What the schema says

The 1.6 JSON reference lists several ways to assert identity: purl, cpe, swid, omniborId and swhid. For omniborId, the spec says to assert identity using the OmniBOR Artifact ID, conforming to the gitoid URI scheme registered with IANA. Its examples look like this.

gitoid:blob:sha1:a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
gitoid:blob:sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08

For swhid, the spec says to assert identity using the Software Heritage persistent identifier, and each field is an array of strings, so a component can have several.

SPDX 2.3 has a matching idea. Its external reference example uses a PERSISTENT-ID category with type swh and a locator such as swh:1:cnt followed by a hash.

How they differ from a purl

IdentifierBased onGood at
purlEcosystem, name and versionMatching packages to registry and vulnerability data
cpeProduct naming schemeMatching some vulnerability databases
omniborIdContent of the artifactShowing two artifacts are bit-identical
swhidArchived content or revisionPointing at a permanent copy in an archive

A purl says what something is called. A content identifier says what the bytes are. If a package is renamed, forked or republished under a new name, the purl changes while the content identifier stays the same.

When they are worth adding

When you vendor or fork code. A copied file has no registry, so no purl. A content identifier lets a later reader link it back to its origin.

When you need to prove which artifact you shipped. A content identifier is an anchor that does not depend on a registry still existing.

When you analyze binaries. If a tool found a component by its contents, recording the content identifier shows how.

When a registry might remove a package. An archive identifier keeps a pointer to a copy.

When to skip them

For ordinary package manager dependencies, a purl and a hash already do the job, and the extra identifiers add maintenance without much benefit. Add them if your tooling emits them for free, but do not build a process around them.

Pair with evidence

CycloneDX evidence identity can name omniborId or swhid as the identity field being substantiated, along with the technique that produced it. That way readers see both the identifier and how it was derived.

Check before sharing

Validate the format. A gitoid with the wrong hash length, or a swhid with a missing prefix, will fail strict parsers. Compare against the examples in the spec and test on a sample file first.

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.

Quick check

Are omniborId and swhid required?

No. The only required component fields in the 1.6 schema are type and name.

Do these replace purl?

No. They identify content, while a purl identifies a package in an ecosystem. They answer different questions.

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.