Nobody Signed Off on This: SBOMs, Agentic Coding, and the Trust Gap

SBOMs are mature, validated, and increasingly required – and they are structurally silent about autonomous agent decisions. I built two repositories for a BSides Cache County talk to make that argument tangible.

The problem in six dependencies

I have a FastAPI service. Three direct dependencies: fastapi, uvicorn, pydantic. Eighteen components total in a CycloneDX v1.6 SBOM. Clean, valid, the artifact we’ve relied on since the 2021 executive order.

Then I pointed Claude Code at it and said: “Add a styled quote endpoint that formats quotes with metadata.”

The agent chose pandas. A 15MB data-science library to format a text string. It added pandas to requirements.txt, ran pip install, regenerated the lockfile, and moved on. Six new transitive dependencies: pandas, numpy, python-dateutil, pytz, six, tzdata. The component count went from 18 to 24.

Both SBOMs – before and after – validate against CycloneDX v1.6. Green. Valid. Nobody signed off on this.

That isn’t a tooling failure. The SBOM faithfully recorded every component. The gap is structural: SBOMs inventory code, not decisions.

What the AIBOM gets right, and where it stops

The OWASP AIBOM Generator extends CycloneDX with ML-specific fields. For a model like google-bert/bert-base-uncased, the AIBOM captures things the traditional SBOM structurally cannot hold:

  • Model lineage and architecture (BERT, fill-mask)
  • Training data provenance (BookCorpus, Wikipedia)
  • Weight identifier (commit hash 86b5e093)
  • Model card considerations and safety assessments
  • Completeness score: 63.4 out of 100

Productized today, real progress. But search that AIBOM for who added pandas, what prompt drove the change, which tool calls the agent made, or what commit introduced it – nothing. Richer BOM. Same blind spot.

Closing the gap with attestation

The fix isn’t a better BOM. It’s a different kind of artifact: an attestation over the agent’s action.

I captured the agent’s session as a structured JSON record – agent identity (claude-code), model (claude-sonnet-4), prompt, every tool call, every dependency added, resulting commit hash – and signed it with cosign as an in-toto predicate:

$ cosign verify-blob \
    --key cosign.pub \
    --signature attestation/agent-action.bundle \
    attestation/agent-action.intoto.jsonl

Verified OK

Same six dependencies. Now with a signed provenance chain: who did it, what model, what prompt, what action, what commit.

This is assemble-it-yourself today – a hand-wired in-toto predicate, a local cosign keypair (keyless via Fulcio in production), no turnkey tooling. But the pattern works and the signature verifies.

The sbom-demo repository has the full narrative as six Makefile targets. Everything is pre-generated and committed – clone it, run make close-the-loop, no network required.

sbom-mirage: the SBOM is lying to you

The talk demo proves the blind spot exists. sbom-mirage proves it’s exploitable, and shows where trust needs to live. Three stages:

Stage 1: Detect

Two simplified SBOM generators parse the same lockfile and produce different results. Real tools genuinely disagree on the same input – component naming, version normalization, license detection. The --mutate flag makes it worse: add a dependency after the SBOM was generated, and the original signed SBOM still passes validation.

$ mirage detect --mutate

The document lies. The signature says it’s authentic.

Stage 2: Vet

Given a package name, an LLM agent with read-only tools (fetch metadata, fetch README, list declared hooks) inspects intent versus behavior. What does the README claim? What do the install scripts actually do? Do the entrypoints match the stated purpose?

It also looks for LLM-targeted persuasion patterns – package READMEs written to convince an autonomous coding agent to select the package. Authority framing (“SYSTEM”-style directives), instruction-like text aimed at a model rather than a human developer. The fixture set includes one package exhibiting this pattern and one benign control.

$ mirage vet suspicious-package

The output is a structured JSON verdict with the full tool-call log. Not a single prompt – a real tool-use loop with capped iterations, auditable end to end. Runs against local Ollama by default, falls back to bundled transcripts when no endpoint is available.

Stage 3: Attest

Compute a SHA-256 content digest of a built artifact, bind a scan result to that exact digest with a real signature, and verify by recomputing the digest – not by re-reading the document.

$ mirage attest sign --artifact ./build/output.tar.gz
$ mirage attest verify --artifact ./build/output.tar.gz

Mutate one byte and verification fails – not because a document was re-checked, but because the digest no longer matches. Trust moves from the document to the build.

Why this matters now

CMMC 2.0 is contractual (DFARS 252.204-7021, enforcement started November 2025). It rests on NIST 800-171 and the concept of an “affirming official” – a named human who vouches for continuous compliance. That is exactly the assumption agentic coding breaks. The affirming official can’t vouch for decisions they didn’t make and may not even see.

SBOMs are moving into acquisition language. A valid, signed SBOM can faithfully record a build that no human reviewed – and nobody downstream would know.

Tier What exists Status
Productized today AIBOM generation (OWASP AIBOM Generator) Real tools, real output
Assemble-it-yourself Agent-action attestation (cosign + in-toto) Pattern works, hand-wired
Where it’s heading Automated capture in CI, keyless signing, policy engines gating on attestation Speculative

The work is between tiers two and three. Keyless signing via Sigstore. Policy engines that gate deployment on both SBOM completeness and agent-action attestation. Spec revisions with first-class fields for autonomous decision provenance. None of that is turnkey yet. The pattern – attest the decision, not just the inventory – is sound, and the signature verifies today.

The repos

  • sbom-demo — Talk demo. Six Makefile targets walking from baseline SBOM through AIBOM to signed attestation. Pre-generated artifacts, no network required. Branch agent-build has the full narrative.
  • sbom-mirage — Research companion. Three-stage CLI: detect SBOM disagreement, agentic package vetting with persuasion-pattern detection, digest-keyed attestation. Runs offline against bundled fixtures or live against Ollama/any OpenAI-compatible endpoint.