SLSA build provenance with GitLab Runner

SLSA build provenance with GitLab Runner records how an artifact was built. This page covers what the feature does, when to enable it, the decisions it forces, and what to confirm before you rely on it.

On this page

How SLSA build provenance with GitLab Runner starts in your pipeline

If you need evidence of where and how a build artifact was produced, whether for an auditor, a customer questionnaire or an internal release gate, the starting point is the build job itself. SLSA 1.0 provenance is a structured build record that describes the source, the build steps and the builder that produced an artifact. With GitLab, the job runner can generate this record during the job when the RUNNER_GENERATE_ARTIFACTS_METADATA variable is set, so the evidence is captured at build time rather than reconstructed afterward. Before enabling it, confirm in the GitLab Runner documentation exactly which metadata the installed version produces, where the files are written and which artifact types are covered, because generation behavior is version specific.

DeployOpen plans and implements this inside your own GitLab instance and runner fleet, so the provenance files stay in infrastructure you control. The first decisions are scope and ownership: which projects and pipelines must produce provenance, which runners execute those jobs, and who owns the variable in CI/CD settings so teams cannot silently turn it off. Confirm that the runner version matches your GitLab version. The GitLab documentation advises keeping the Runner major and minor versions aligned with GitLab, and a mismatch is the first thing to rule out when metadata is missing. Ask your team which runner executor types are in use, since that determines the build environment the provenance describes.

Plan the storage and verification path before the first build runs. Provenance files are only useful if they are kept alongside the artifacts they describe, retained for as long as those artifacts are, and checked by a consumer who knows what to expect. Decide where the metadata is stored, how release gates read it and what happens when a job produces none. A short pilot on one project, with the outputs inspected by someone outside the pipeline team, will show whether the evidence meets the audit or customer requirement before it is rolled out across the organization.

What the in-toto statement carries and why verifiers read it

Provenance arrives as an *in-toto statement*, a JSON envelope that names the artifact by its digest and then describes how that artifact was built. The subject entry is the anchor: it records the artifact's name and cryptographic digests, so anyone holding a file can recompute the digest and confirm it is the same object the build produced. The predicate is the part that describes the build itself, covering the builder that ran it, the source repository and revision, the build steps and the parameters passed in. Your team should not assume which predicate fields GitLab emits for a given Runner release. Confirm the field list in the Runner documentation for your version, then generate a sample from a test pipeline and read the file yourself before writing any verification logic against it.

A verifier reads the statement to answer three questions, and each one needs a decision made in advance. First, do the subject digests match the artifact in hand? A mismatch means the file was changed after the build or is not the file the statement describes. Second, is the builder one you trust? The statement only means something if the builder identity is on your allowlist, and that identity is usually the Runner or the pipeline context it reports. Third, is the source revision the one you expect? A valid statement for an unexpected branch, tag or repository is still a failed check. Write these three rules down as the acceptance criteria for your release process, because a verifier that checks only the signature or only the digest answers less than it appears to.

The statement is only as useful as your ability to find it later, so plan where the metadata files live before the first release. Confirm with your Runner version whether the metadata is written as a job artifact, how long that artifact is retained, and whether your artifact repository keeps it alongside the binary it describes. Metadata stored apart from the artifact, or pruned by a retention rule, cannot support an audit months later. Ask your team to test one full cycle: build, download the artifact and its metadata, recompute the digest, and run the checks against the expected builder and revision. An illustrative example of a failed check is a tag rebuilt from a different commit, which the source revision rule should catch.

Configuring SLSA build provenance options in GitLab Runner

This table compares the four decisions teams make when turning on provenance generation with RUNNER_GENERATE_ARTIFACTS_METADATA: how widely the variable applies, which builds get it, where the metadata lives and who checks it. Read each row against your release process, and confirm the specifics against your GitLab Runner version and the current documentation before you commit to a pattern. The main takeaway is that scoping and verification placement usually matter more than the variable itself.

DecisionWhen it fitsMain trade-offWhat to confirm
Variable per jobA few pipelines produce the artifacts that ship, and other jobs should not carry the extra step.Each new pipeline must remember to set the variable, so coverage can drift as teams add jobs.Which jobs produce shipped artifacts, and how reviewers check that the variable is present.
Variable project-wideMany projects share one build template and you want every build to produce metadata by default.Non-release builds also produce metadata, which adds artifacts to store and review.Whether your Runner version and template support the variable as you expect in every project.
Scope to release branches or tagged buildsOnly builds that reach production or customers need a verifiable origin record.Development builds have no provenance, so a problem found in a branch build cannot be traced the same way.Your release branch and tag naming rules, and whether protected tags are enforced in each project.
Keep metadata beside artifactsYour consumers pull artifacts from GitLab and you want one place to find the build and its record.Metadata lives under the same retention and access rules as the artifacts, so deleting artifacts can remove the record too.Artifact retention settings, and who can read or delete job artifacts in each project.
Send metadata to a separate attestation storeRecords must outlive pipeline artifacts or be kept apart from the teams that build them.Another system adds integration, access control and backup work that your team must own.Which store your assessors accept, how records are indexed to artifact digests, and who operates the store.
Verify in a deploy jobYour deploy pipeline is the gate, and failing a deployment on a bad record is the control you need.Verification logic lives in pipeline code, so it must be maintained and protected like other deploy code.Which verifier tool and version the deploy image uses, and whether failures block deployment or only warn.
Verify with an external verifierSeveral teams or environments deploy the same artifacts and need one independent check.A separate service adds an extra step and a dependency, and its own trust and uptime concerns.Who owns the verifier, how it receives artifacts and metadata, and how it is updated and audited.

Setting up provenance generation on a self-managed instance

This sequence takes a self-managed GitLab instance from version alignment to a verified provenance file attached to a build artifact. Each step ends with a check, so the platform team knows the metadata is being generated, recorded and consumed before the pattern is copied to other projects.

  1. Confirm version alignment and support status

    The platform team checks that the GitLab instance and the GitLab Runner fleet run aligned major and minor versions, as the Runner documentation advises, and that both sit on a release line GitLab currently maintains under its maintenance policy. Confirm the current maintained releases on the policy page before you touch the Runner configuration, since bug fixes are backported only to the current stable release and security fixes reach the previous two monthly releases. The step is done when the versions are recorded in your change ticket and both components are inside the supported window.

  2. Choose and verify the executor

    The Runner owner selects the executor the build will use, whether shell, Docker or an autoscaling executor on cloud VMs or hypervisors, and confirms that this executor can write the metadata file into the job workspace and upload it as an artifact. Ask the Runner administrator to run a trivial job on that executor that writes a file and publishes it as an artifact, so permission and path problems surface before provenance depends on them. The step is done when a test artifact downloads from the job page with the expected contents.

  3. Enable the variable on a test project

    The pipeline owner sets RUNNER_GENERATE_ARTIFACTS_METADATA on a non-production project, either in the CI/CD settings or in the .gitlab-ci.yml file, and keeps the change scoped to that project. Enable it only on the build job that produces the artifact you care about, and avoid setting it globally until the output has been reviewed. The step is done when the variable is visible in the pipeline configuration and the next job log shows the Runner reading it.

  4. Run a tagged build and inspect the metadata

    The developer runs a build on a protected tag or a test branch that produces a real artifact, then opens the job artifacts and inspects the generated provenance file. Check that it is an in-toto statement, that its predicate type identifies SLSA provenance version 1.0, and that the subject entry names the artifact with a digest. Confirm that the builder, the source repository and the commit are the values you expect for this project. The step is done when the file matches these checks and a second run from the same commit produces a consistent subject digest.

  5. Record the artifact digest against the job

    The release engineer records the artifact digest from the provenance subject, the pipeline ID, the job ID and the commit SHA in the release record or your change management system. This creates the link auditors and downstream consumers will follow from a released binary back to the build that produced it. Store the provenance file alongside the artifact in the same retention policy, rather than leaving it only in the pipeline job. The step is done when a person outside the pipeline can locate the artifact, its digest and its provenance from the release record alone.

  6. Add a verification step to a downstream job

    The pipeline owner adds a downstream job that runs after the build, retrieves the artifact and provenance file, recomputes the artifact digest and compares it with the subject in the statement. The job should fail if the digests differ or if the predicate type is not the expected one, so a tampered or mismatched artifact stops the pipeline before deployment. Keep the verifier's own image and scripts under the same change control as the build. The step is done when a deliberately altered artifact in a test run causes the verification job to fail.

  7. Document the air-gapped runner procedure

    If the Runners sit in an offline or air-gapped network, the platform team documents how images, runner binaries and any verification tools reach those hosts, and confirms that the provenance step needs nothing that is unavailable offline. Confirm this against the GitLab offline environments guidance and your own mirroring process, and do not assume an internet call is absent. Write the procedure into the runbook with the owner of each mirror. The step is done when an engineer can repeat the test build and verification on an isolated Runner using only the documented steps.

Storing and verifying SLSA build provenance metadata

Decide where the provenance metadata lives before the first release is built, because the storage choice sets how long the evidence survives and who can read it. The metadata can stay as a job artifact with a defined retention period, which is the simplest option but ties the evidence to GitLab's own artifact lifecycle. Pushing the statement alongside the container image or package in the registry keeps it next to the thing it describes, so a consumer who pulls the artifact can find its provenance. Copying the files to an external evidence store that the security team controls gives the most independence from the build platform, at the cost of an extra export step that must be tested like any other pipeline job. Pick one primary location and document it, and note which copy is authoritative if two exist.

Verification means recomputing the digest of the delivered artifact and comparing it with the subject entries in the in-toto statement, then checking the builder and source fields against the values your policy expects, such as the approved project path, the protected branch or tag, and the runner or builder identity. A signature check on the statement, where you use one, belongs in the same step. Retention and access should match your audit period, not the default artifact expiry, so plan how long statements, the artifacts they describe and the pipeline logs are kept, and who may read or delete them. Finally, confirm with each consumer which verification tooling they run and which provenance format and version it accepts, because a statement that no downstream system can check provides little assurance. Confirm these details against the current GitLab Runner documentation for your version.

Protecting the runner and the provenance trust chain

Provenance is only as trustworthy as the system that produced it. The cards below cover the places an attacker or careless configuration can alter a build, its secrets, its metadata or its records, and the controls that narrow each gap. Confirm each item against your own runner fleet and repository settings before you rely on the attestation.

Runner compromise alters artifact and metadata

A runner that executes a job can change the built artifact and the metadata describing it in the same run, so the attestation may faithfully describe a tampered build. Keep runners for protected branches on dedicated, single-purpose infrastructure, and avoid shared executors that serve untrusted projects. Confirm which runners can pick up jobs from protected refs and whether the executor is ephemeral.

Secrets exposed to build jobs

Any credential a build job can read is available to code that job runs, including a malicious dependency or a modified script. Limit signing keys and registry credentials to protected variables scoped to protected branches and tags, and keep them out of merge request pipelines from forks. Confirm which variables are masked, protected and scoped to the environments that produce release artifacts.

Unsigned metadata that can be replaced

If provenance files are only stored as job artifacts, anyone with write access to the pipeline or the project can overwrite them with a different statement. Treat the metadata as evidence that must be checked, not trusted by location, and verify the digest of each artifact against the statement before deployment. Confirm who can edit pipeline configuration and whether artifact uploads from non-protected jobs can overwrite release outputs.

Restricted write access to pipelines

Provenance proves what a pipeline did, so control over the pipeline definition controls the claim. Restrict who can merge to protected branches, require approvals for changes to CI configuration, and limit maintainer roles to people who need them. Confirm the approval rules that apply to .gitlab-ci.yml and to any included template that the release pipeline loads.

Over-broad retention and access to records

Build records and attestations often outlive the artifacts they describe, and broad project access exposes them to people who should not see build details or internal paths. Set retention for provenance files to match your audit and release obligations, and limit who can download job artifacts. Confirm the expiry settings in your instance and whether the metadata is copied to a store with its own access controls.

Tamper-evident storage for attestations

Storing metadata in a location where it can be silently edited weakens every later check. Copy attestations to an append-only or write-once location controlled by a separate team, and record the digest of each file at creation. Confirm which system holds the signed copy, who holds its keys, and how a reviewer would detect a replaced file.

What does SLSA build provenance implementation cost and take?

What drives the effort of setting up SLSA provenance in GitLab?

The effort scales with how many pipelines produce artifacts, how many runner types build them, and where those artifacts end up. Each pipeline that emits build artifacts needs the metadata option configured and tested, and each runner type (shell, Docker, autoscaling or Kubernetes) may need its own check before you trust its output. Artifact registries, package repositories and any downstream systems that consume the metadata files add more work, because each one needs a storage and retrieval decision. Air-gapped instances add constraints on how verification tools and trust material reach the network. Ask any partner to break the estimate down by these dimensions rather than quoting one number for the whole program.

Does SLSA provenance need a specific GitLab tier?

Confirm this before you budget. The GitLab pricing page lists Free at no cost, Premium at 29 US dollars per user per month billed annually, and Ultimate as custom priced, and it states that all three tiers are available for self-managed installations. The page lists software supply chain security under Ultimate, but it does not spell out every provenance-related capability by tier. Check the current Ultimate listing and the feature documentation for the exact release you run, and get the answer in writing from GitLab or your reseller before you assume a tier covers the work.

What recurring work follows a SLSA provenance launch?

Most of the ongoing cost is operational, not one-time configuration. Runner versions need to stay aligned with your GitLab version, which follows the monthly minor releases, twice-monthly patch releases and yearly major releases described in the GitLab maintenance policy. Upgrades also have to pass through required upgrade stops, so runner and pipeline changes should be retested at each stop. Teams also need to decide how long provenance files are retained alongside the artifacts they describe, and verification tooling needs updates as the format and checks change. Ask for these items as named recurring tasks with owners in any quote.

What must our team provide before implementation starts?

Expect to supply access and a safe place to test. That means administrator or maintainer access to the GitLab instance, a non-production test project that mirrors a real build, and access to the runners that will execute the jobs. You also need named owners for decisions that the work cannot make alone: who approves the signing and verification policy, who owns artifact retention, and who receives verification failures. For air-gapped instances, the team must supply the internal mirrors and transfer process for any tools or data the verifier needs. Agree these inputs in the written scope so delays are visible early.

Can our internal platform team implement SLSA provenance alone?

A capable platform team can often handle a single pipeline and a single runner type with the GitLab documentation and a test project. The harder part is cross-team: aligning build owners, security reviewers and the people who verify artifacts on the consuming side. Teams usually struggle when several runner fleets, multiple registries or regulated evidence requirements are involved, because each change touches release engineering and audit preparation. Assess your team's Runner, CI/CD and security skills honestly, and decide whether a pilot on one project is enough to prove the approach before you scale it.

What risks should we plan for during rollout?

The main risks are incomplete coverage, inconsistent runner behavior and metadata that nobody checks. If only some pipelines generate provenance, the gaps are easy to miss and hard to explain to an assessor. Mixed runner versions or executor types can produce metadata that differs in detail, so test each combination you run. Provenance that is generated but never verified gives little assurance, so define who checks it and what happens on failure. Plan a staged rollout that starts with one project and expands only after verification passes.

What should we ask for in a written quote for this work?

Ask for a scope that lists the pipelines, runner types, registries and verification consumers in scope, with each one named. Request the deliverables in writing, such as the configured pipelines, test evidence, verification procedure, runbook and handover notes. Ask which items are one-time and which recur, including runner upgrades, retention review and verifier updates, and whether recurring support is a separate retainer. Confirm which GitLab tier and features the design assumes, and what the quote excludes, such as tier upgrades, licensing or hardware. Most DeployOpen engagements are fixed-scope, so a written scope is the basis for any quote.

Limits to confirm in your environment

Provenance generation depends on versions, tier, executors, update channels, consumers and signing choices, and each one can block the pipeline in a different way. The cards below set out what to verify and where to verify it before you build the workflow around GitLab's metadata output.

Runner and GitLab version support

The RUNNER_GENERATE_ARTIFACTS_METADATA variable and the metadata format are tied to specific GitLab and Runner releases. Confirm that your GitLab instance and every Runner in the fleet support the variable and the output schema you plan to consume. Keep Runner major and minor versions aligned with GitLab, as the Runner documentation advises, so that a mismatch does not silently produce no metadata. Check the GitLab Runner docs for the version that introduced the feature before you pin versions.

Tier and feature entitlement

Confirm which GitLab tier your instance holds and whether the provenance feature and its surrounding security features fall within it. The pricing page lists advanced CI/CD and priority support for Premium, and application security and supply chain security for Ultimate, so do not assume a feature is included because the pipeline runs. Ask your GitLab account contact to confirm in writing for your tier and deployment type.

Executor support for your build types

Metadata generation depends on how jobs run. Shell, Docker and autoscaling executors differ in how they isolate builds, handle the workspace and expose the build environment. Test each executor you use, including Docker Autoscaler on cloud VMs and the Kubernetes executor, with a representative build that produces artifacts. Record the output for each executor so you know which fleet members can be trusted to emit provenance.

Offline Runner updates

In air-gapped environments, Runner binaries, container images and any dependencies must be mirrored into the network before they can be deployed. Plan how a new Runner release reaches your offline fleet, who approves it and how the version stays aligned with the GitLab instance. A Runner that lags behind the instance may not emit the metadata you expect, and the lag can go unnoticed until an auditor or consumer asks for it.

Downstream consumer acceptance

Verification only helps if the systems that consume the attestation understand the in-toto statement format. Ask each consumer, whether an internal policy engine, a deployment gate or an external customer, which statement type and predicate they accept, and whether they validate the subject digests against the artifacts they receive. If a consumer cannot read the format, the metadata will be stored but not used, and the control will not work as intended.

Signing beyond GitLab's output

Confirm how the metadata is protected after GitLab emits it. An unsigned statement proves what the pipeline recorded but does not by itself prove who recorded it or that it has not been changed. Decide whether you need a separate signing step with keys held in your secrets manager, how keys are rotated, and where verification runs. Treat this as a design decision to make with your security team, and confirm exactly what GitLab's output does and does not sign in the current documentation.

How DeployOpen scopes and delivers provenance on self-managed GitLab

DeployOpen plans, implements, tests, documents and supports self-hosted open-source platforms inside your own infrastructure, including GitLab and its CI/CD runners. For SLSA build provenance, we start from the pipelines and artifacts you need to attest, then agree the scope in writing before any work begins.

How we scope

  • Inventory the build pipelines, runner executors and artifact types that need provenance metadata.
  • Confirm which GitLab tier and runner version your instance supports before any configuration begins.
  • Agree in writing which verification steps, storage locations and retention rules the engagement covers.

How we build

  • Enable artifact metadata generation in the pipelines in scope and review the generated in-toto statements.
  • Test verification with the consumers who will check the attestations, using a sample release from a non-production project.
  • Document any runner or pipeline changes so they can be repeated across other projects in your group.

How we hand over

  • Deliver the pipeline configuration, verification scripts and storage layout as versioned files in your repositories.
  • Provide written runbooks covering how to read, store, verify and rotate the provenance metadata over time.
  • Walk your platform, security and release engineers through the handover so they can operate the setup without us.

How we support

  • Offer ongoing support, upgrades and continuous testing as a retainer after the fixed-scope engagement ends.
  • Review provenance output again when GitLab or runner versions change, following the upgrade stops you plan.
  • Ask your team to confirm current behavior and version support with GitLab documentation before each change.

Sources and further reading

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.