5 min read
A runner-image SBOM is not build provenance
What the runner SBOM tells me
A runner-image SBOM answers a useful, bounded question: what software was preinstalled in this build environment? GitHub says SBOMs are available for its maintained Ubuntu, Windows, and macOS runner images, and that they can be found among the assets attached to image releases. Its secure-use reference describes using the inventory to inspect software on the runner and scan it for vulnerabilities.
That is valuable evidence. If an image contains a vulnerable preinstalled tool, its inventory can help identify which image release needs attention. It can also help explain the starting environment a job received. I would preserve the relevant SBOM alongside build records rather than treating it as disposable documentation.
But “what was installed on the runner” is not the same question as “what influenced this artifact.” The SBOM describes the image, not necessarily the full execution of a particular job. A workflow can download dependencies, execute actions, run scripts from the repository, call external services, or produce intermediate files during the build. Those inputs and operations are not established merely by listing the image’s preinstalled software. That distinction follows from the scope of the inventory: it describes the image, while the artifact results from a process using that image.
The build has more inputs than its machine image
A workflow definition is part of the recipe. It identifies the jobs and steps, their order, and the actions or commands used. The source revision matters too, as do dependency versions and configuration passed to the build. Some inputs are fixed in the repository; others may be fetched or resolved while the job runs.
Consider a small workflow:
name: Build
on:
push:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: dotnet restore
- run: dotnet publish --configuration Release
This snippet says something about the runner label and the steps, but it does not, by itself, identify the exact runner image revision used for a particular execution. The label is a selection, not a permanent image identity. Nor does the snippet record the resolved dependency graph produced by restore. The action reference is a version tag rather than an immutable commit reference. GitHub’s secure-use guidance recommends pinning actions to a full-length commit SHA, describing that as the only way to use an action as an immutable release.
Pinning helps make the action reference more specific, but it does not make the runner SBOM a record of everything else. A complete account of the build would still need to connect the chosen image and its inventory to the workflow revision, source revision, resolved action references, dependency inputs, and the artifact itself. Depending on the build, it may also need to capture parameters or external materials that affected the result.
I find it helpful to keep two questions separate. An SBOM describes components or software in an inventory. Provenance describes how an output was produced and what inputs and platform were involved. The SLSA terminology defines provenance as metadata describing how outputs were produced, including identification of the platform and external parameters. That is a wider record than a runner-image inventory.
Connect evidence to a particular build
Evidence becomes useful when it has an unambiguous relationship to the build and output it is meant to explain. A runner-image SBOM attached to a workflow run without an image identity or release reference may be difficult to match later. Even when the SBOM is known, a reviewer needs to know which workflow and source revision produced the artifact, and which external actions and dependencies the job consumed.
I would make the evidence chain explicit. Record the artifact’s digest so the record refers to the produced bytes rather than just a mutable filename or tag. Record the workflow identity and source revision. Record the runner image identifier and associate it with the matching image SBOM. Record the action references and dependency inputs used by the run. Keep those records together or link them through stable identifiers, and make the evidence available to the people who need to verify the artifact.
This is not a claim that every build can capture every possible influence perfectly. Builds can depend on network responses, environment variables, generated files, or other state that is easy to overlook. The practical goal is to identify the inputs that matter, preserve enough detail to trace the artifact back to them, and be clear about what remains outside the record. A list of installed software alone cannot close those gaps.
GitHub offers artifact attestations as another part of this picture. Its documentation on build provenance attestations explains how workflows can generate attestations for artifacts. GitHub describes these as signed claims that can associate an artifact with information such as its workflow, repository, environment, commit SHA, and triggering event. That makes an attestation more directly relevant to the question of where an artifact came from than a runner-image SBOM alone. I would still inspect what the attestation actually covers and what inputs the build record captures; the existence of an attestation is not a reason to assume every relevant influence has been recorded.
Use the SBOM for the question it answers
I would keep the runner-image SBOM, but label its role accurately: it is evidence about preinstalled software in a runner image. It can support vulnerability review and help describe the environment. It cannot, on its own, prove which exact workflow, actions, source revision, or fetched dependencies produced a particular artifact.
That distinction changes how I would design a CI evidence bundle. Start with the artifact identity, then link the build record to the exact source and workflow, the runner image and its SBOM, and the actions and dependencies used. If a link is missing, mark the gap instead of letting an inventory stand in for evidence it does not contain. A useful SBOM is one component of the record; the value comes from connecting it to the build it is supposed to describe.
Drafted with AI assistance, reviewed and edited by Ali.