CI/CD integration

The target pipeline

1. build           → produces the artefact
2. sbom-generate   → build SBOM + analysed SBOM
3. sbom-validate   → schema, quality score, build/analysed gap
                     ↳ FAIL below threshold
4. sbom-sign       → signature + provenance attestation
5. sbom-publish    → send to the steering platform
6. policy-gate     → vulnerabilities, licences, VEX
                     ↳ FAIL or WARN depending on policy
7. attach          → SBOM and signature attached to the artefact in the registry
8. archive         → deposited in the evidence vault, indexed by hash

Steps 3 and 6 are blocking. The others are production steps: their failure must also fail the build, or artefacts without an SBOM will reach production.

Example — GitHub Actions

jobs:
  build-and-attest:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      id-token: write      # keyless signing, no long-lived secret
      packages: write
    steps:
      - uses: actions/checkout@v4

      - name: Build the artefact
        run: make build

      - name: Generate the SBOM (build)
        run: syft dir:. -o cyclonedx-json=sbom-build.cdx.json

      - name: Generate the SBOM (analysed)
        run: syft "$IMAGE" -o cyclonedx-json=sbom-analyzed.cdx.json

      - name: Validate quality and gap
        run: ./ci/validate-sbom.sh sbom-build.cdx.json sbom-analyzed.cdx.json

      - name: Sign
        run: cosign attest --predicate sbom-build.cdx.json --type cyclonedx "$IMAGE"

      - name: Publish to the platform
        run: ./ci/publish-sbom.sh sbom-build.cdx.json

      - name: Policy gate (vulnerabilities and licences)
        run: ./ci/policy-gate.sh sbom-build.cdx.json

The principle is the same on GitLab CI, Jenkins or Azure DevOps: the steps are identical, only the syntax changes. The validate-sbom.sh, publish-sbom.sh and policy-gate.sh scripts are shared across all chains and versioned in a central repository — that is what makes thresholds uniform.

The blocking rules

Condition Effect Rationale
SBOM not generated or schema invalid Fail Without an SBOM there is no possible compliance
Quality score below threshold Fail An incomplete SBOM gives false assurance
Build / analysed gap above threshold Fail Reveals undeclared code
Critical exploitable vulnerability, no VEX Fail Annex I: no known exploitable vulnerability at placing on the market
High-severity vulnerability, no VEX Warning + ticket Handled within the SLA
Licence on the deny list for this context Fail Licence policy
Licence on the review list Warning + ticket Legal review
Signature or attestation missing Fail Without a signature, the SBOM is not evidence

Waivers

A block with no escape hatch gets bypassed, usually by disabling the check. A controlled waiver is therefore needed:

  1. requested through a ticket, with justification;
  2. granted by a named person — the CISO for vulnerabilities, Legal for licences;
  3. time-limited, with a mandatory expiry date;
  4. recorded in a versioned file alongside the code, readable by the pipeline;
  5. automatically expired: on the date, the block resumes.

A permanent waiver is a change to the policy, and must be treated as one — not as an exception.

Special cases

Monorepos. One SBOM per publishable artefact, not one per repository. The difficulty is attributing shared dependencies correctly; native build-chain plugins handle this better than generic generators.

Matrix builds. One artefact per OS or architecture combination, therefore one SBOM per combination. One variant’s SBOM does not hold for the others.

Incremental builds and caching. Caching can mask a dependency change. The SBOM must be regenerated for every publishable build, with no cache reuse.

Repackaged third-party artefacts. If you republish an artefact you did not build, you must analyse it — the supplier’s SBOM, where it exists, is a starting point to verify, not a document to adopt as is.

The cost

Generation adds anywhere from seconds to minutes per build, depending on artefact size and method. The usual levers:

  • produce the analysed SBOM only on publishable builds, not on every pull request;
  • cache the tools’ vulnerability databases, not the results;
  • parallelise generation with the test suite;
  • reserve the full cross-check for release branches.

None of these optimisations may reduce what is produced for a shipped artefact: that is the only case where compliance is at stake.