How do I sign an SBOM?

TL;DR

You should always sign your SBOMs so that consumers never need to trust the transportation layer. Whether you use GitHub Attestations, Sigstore, X.509 certificates, or PGP, a signed SBOM lets the recipient verify authenticity and integrity directly back to the issuing party.

Why signing matters

An unsigned SBOM is a claim. A signed SBOM is evidence.

Without a signature, anyone who receives your SBOM has to trust every system it passed through - your CI pipeline, the SBOM management platform, the file transfer, the download link. If any of those are compromised, the SBOM could be silently altered, and the recipient would never know.

Signing eliminates this problem. A cryptographically signed SBOM lets the consumer verify two things independently:

  1. Authenticity - the SBOM was produced by your organization’s CI/CD pipeline, not fabricated by a third party
  2. Integrity - the SBOM has not been modified since it was signed, regardless of how many systems it passed through

This means you never need to trust the transportation layer. Whether the SBOM is hosted on sbomify, downloaded from a Trust Center, or received via email, the signature lets you trace it back to the issuing party and verify it has not been tampered with.

Signing must be the last step

A signature is a cryptographic seal over the exact bytes of the SBOM. Any tool that modifies the SBOM after signing - whether it adds fields, strips whitespace, re-formats JSON, merges data, or converts between formats - breaks the chain of trust. The signature no longer matches the file, and verification will fail.

This means that all enrichment, augmentation, and transformation must happen before signing. If you need to modify a signed SBOM for any reason, you must re-sign it afterward, and the new signature will reflect the new signer’s identity rather than the original issuer’s. This is by design: the signature proves exactly who produced the final artifact.

In practice, this is why sbomify-action’s pipeline runs augmentation and enrichment first, then writes the final SBOM to disk, and only then passes it to the attestation step. Any tool that modifies an SBOM post-generation and post-signing - even with good intentions - invalidates the attestation and forces a re-sign.

How to sign an SBOM with GitHub Attestations

The simplest way to sign an SBOM today is with GitHub’s built-in attestation support. Behind the scenes, it uses Sigstore for keyless signing and the in-toto attestation format - but you do not need to manage any keys or understand the underlying protocols.

In your GitHub Actions workflow, generate the SBOM and then pass it to the attestation action:

- name: Generate SBOM
  uses: sbomify/sbomify-action@master
  env:
    TOKEN: ${{ secrets.SBOMIFY_TOKEN }}
    COMPONENT_ID: 'your-component-id'
    LOCK_FILE: 'requirements.txt'
    AUGMENT: true
    ENRICH: true
    UPLOAD: true
    OUTPUT_FILE: sbom.cdx.json

- name: Attest SBOM
  uses: actions/attest-build-provenance@v1
  with:
    subject-path: '${{ github.workspace }}/sbom.cdx.json'

That is it. GitHub signs the SBOM using your workflow’s identity, records the signature in a Sigstore transparency log, and links it to the exact repository and workflow run that produced it.

Verifying a signed SBOM

Anyone can verify a signed SBOM using the GitHub CLI:

gh attestation verify path/to/sbom.cdx.json --owner your-org

A successful verification confirms:

  • The SBOM was generated by a specific GitHub Actions workflow
  • It was produced from a specific repository and commit
  • It has not been modified since signing

This is exactly the point: the consumer does not need to trust sbomify, your CDN, or any other intermediary. They can independently verify the SBOM’s provenance by checking the attestation against the Sigstore transparency log.

We use this exact workflow for our own sbomify-action SBOM. You can download the SBOM from our public Trust Center page and verify it yourself. For a detailed walkthrough, see our attestation blog post.

What is happening under the hood

When you sign an SBOM with GitHub Attestations, several things happen:

  1. Sigstore keyless signing - a short-lived certificate is issued based on the workflow’s OIDC identity. No long-lived keys to manage or rotate.
  2. in-toto attestation format - the SBOM digest and build provenance are wrapped in a standardized SLSA provenance predicate inside an in-toto envelope.
  3. Transparency log - the signing event is recorded in Sigstore’s Rekor transparency log, creating tamper-evident, publicly auditable proof that the signature existed at a specific time.

The combination means the signature is tied to a verified identity (your GitHub repository and workflow), recorded in an immutable log, and verifiable by anyone - without any key distribution.

sbomify attestation verification

sbomify can verify attestations automatically when you upload signed SBOMs. The GitHub Attestation Plugin uses Sigstore and cosign to check signatures on upload, giving you a verified provenance status for every SBOM in your portfolio.

This closes the loop: your CI pipeline signs the SBOM, sbomify verifies the signature on ingestion, and your customers can independently verify the same signature when they download the SBOM from your Trust Center.

Alternative: signing with your own certificates

GitHub Attestations and Sigstore are not the only way to sign an SBOM. Organizations that already have their own certificate infrastructure can sign SBOMs using standard X.509 certificates and their existing signing keys. The principle is the same: cryptographically bind the SBOM to a known identity so that consumers can verify authenticity and integrity, without depending on an external service like Sigstore or GitHub.

Both CycloneDX and SPDX 3.0 support inlining the signature directly within the SBOM document. This makes the SBOM a self-contained bundle where the data and its proof of authenticity travel together in a single file. The trade-off is that both generation and verification are more involved. To sign, you generate the SBOM, sign the content, then assemble the final document with the signature embedded. To verify, you need to disassemble the SBOM to separate the signature from the content, validate the certificate chain (and obtain the public key if the certificate is self-signed), and then verify the signature against the original content. It is more work than running gh attestation verify, but the benefit is that everything is in one place and the workflow integrates naturally with enterprise signing infrastructure.

It is also possible to sign SBOMs using PGP, though this is less common today given the shift toward Sigstore’s keyless model and X.509 certificate-based signing.

Whichever method you choose, the core guarantees are the same: the recipient can verify who produced the SBOM and confirm it has not been altered since signing. The best approach depends on your existing infrastructure and your consumers’ verification capabilities.

Further reading