Skip to content
Latchkey

What Is a Poisoned Pipeline Execution? Running Untrusted Code With Secrets

A poisoned pipeline execution (PPE) is an attack where someone gets the CI pipeline to run code they control, with all the secrets and privileges the pipeline holds.

PPE is one of the sharpest CI attacks because it abuses the pipeline's own trust. The attacker does not breach your servers; they get your pipeline to run their code for them, complete with your secrets, your deploy keys, and your signing identity. The most common door is a pull request from an untrusted contributor.

How PPE works

The attacker influences what the pipeline executes, by editing the pipeline file, a build script, or a config the pipeline reads, and arranges for that change to run with secrets attached. The pipeline, trusting its own configuration, dutifully executes the hostile code.

Direct, indirect, and public PPE

  • Direct: the attacker edits the pipeline definition itself.
  • Indirect: they edit something the pipeline runs (a script, a Makefile).
  • Public: a fork pull request triggers a privileged workflow.

The fork pull request trap

The classic public PPE: a workflow runs on pull requests with access to secrets. An outside contributor opens a PR that modifies the build to dump secrets to their server. The pipeline runs the PR's code before any human reviews it. Triggers like pull_request_target are notorious here.

Preventing PPE

Do not run untrusted code with secrets: withhold secrets from fork PR workflows, require approval before privileged runs on external contributions, treat pipeline and build files as protected code needing review, and pin actions to trusted versions.

Containing a PPE that lands

Defense in depth assumes prevention can fail. Least-privilege tokens, ephemeral credentials, egress filtering, and isolated runners mean even a successful PPE finds few secrets, cannot send them anywhere, and cannot persist. The blast radius stays inside one disposable job.

Key takeaways

  • A poisoned pipeline execution runs attacker code with the pipeline's privileges.
  • Fork pull requests that get secrets are the classic public PPE vector.
  • Withhold secrets from untrusted runs and contain with least privilege and isolation.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →