Buildkite signed pipelines make agents verify a cryptographic signature on each step before running it, so a modified step is refused. They protect the instructions, not the output. To trust the artifacts a pipeline produces you also need artifact signing and provenance, verified at deploy time.
What does the signature cover?
Per Buildkite's docs, pipelines are signed when uploaded and agents verify the signature before running the job. On mismatch, the agent refuses the job. The signed fields for each step are:
- the commands
- environment variables defined in the pipeline YAML
- plugins and their configuration
- the matrix configuration, signed as a whole
- the repository the commands run in, which stops a signed step being copied to another repository
That list also shows the gaps. Buildkite states that environment variables set by the agent, hooks or the shell are not signed and can override the environment a command starts with. So a compromised agent host or hook can still change behaviour.
What does it defend against?
The threat is a party who can alter a job in flight, including Buildkite itself being compromised. Buildkite describes this as moving towards zero-trust CI/CD by isolating you from the control plane. Constructed example: an attacker with access to the pipeline settings edits a step to add a curl that posts secrets. Unsigned, the agent runs it. Signed, the signature no longer matches and the job is refused.
Limits from the docs: it works on self-hosted agents, not Buildkite hosted agents, and signed steps cannot be used with pipeline templates because the repository is part of the signature.
How do you set it up?
You generate a JSON Web Key Set, configure agents, and sign steps on upload. The agent includes a keygen tool, buildkite-agent tool keygen, with EdDSA as the default algorithm; PS512 and ES512 are also supported. Keys can instead be managed in AWS KMS or GCP KMS.
Buildkite recommends separate agent pools on separate queues: uploader agents hold the private key, runner agents hold only the public key. A compromised runner then cannot forge signed steps.
Note a documented detail: PS512 and ES512 are nondeterministic, so signatures differ each time, which can make drift detection harder with persisted results such as Terraform.
What about the artifacts?
A pipeline signature says "these steps are what we wrote." It does not say "this binary came from those steps." For that, add:
- Artifact signing, for example Sigstore cosign, where a certificate ties a short-lived key to an identity and the event is logged in Rekor.
- A provenance attestation in the SLSA format recording source revision, builder and inputs. SLSA's levels start at "provenance exists" and rise to hardened builds.
- Verification at the deploy gate that checks signer identity and source revision, not just that a signature exists.
Check Buildkite's current docs for any built in artifact attestation features before building your own; we did not confirm one when writing this.
Safeguard can sit at the gate side: policies and gates evaluate dependencies and findings in a pull request, and the SBOM view shows what went into the artifact.
What to do
- Enable signed pipelines on self-hosted agents with EdDSA keys or a cloud KMS.
- Split uploader and runner pools so runners never hold private keys.
- Audit hooks and agent environment settings, since those are not signed.
- Sign artifacts and generate SLSA provenance in the same pipeline.
- Verify signer identity and source revision before deploy.
- Rotate signing keys on a schedule and test a rotation once.
Quick check
Are environment variables set in agent hooks signed?
No. Buildkite says only variables defined in the pipeline YAML are signed. Variables from the agent, hooks or shell are not.
Does a signed pipeline mean the artifact is trustworthy?
Not by itself. It protects the steps. Artifact signing and provenance, checked at deploy, protect the output.
Sources
- Signed pipelines, Buildkite Docs, fetched 18 October 2026
- SLSA levels, slsa.dev, fetched 18 October 2026
- Cosign signing overview, Sigstore, fetched 18 October 2026
Last reviewed: 18 October 2026.