Blog

OWASP CI/CD Part 4: Poisoned Pipeline Execution (PPE)

May 29 2025/6 min read
Picture of Nigel Douglas
by Nigel Douglas

Modern development teams often rely on Continuous Integration (CI) pipelines to automate testing, building, and deployment of their code These pipelines are typically defined through configuration files stored within the source code repository. Developers, DevOps engineers, or other contributors with the appropriate permissions frequently need to edit these files to adjust workflows, add new checks, or support evolving project requirements.

However, if a user with access to these configuration files (or to other files that the CI pipeline consumes) intentionally or inadvertently introduces malicious commands, they can compromise the security of the CI process. This is known as “poisoning”, where the altered pipeline executes unauthorized or harmful commands during its automated runs.

What is Poisoned Pipeline Execution (PPE)?

Poisoned Pipeline Execution (PPE) occurs when malicious actors exploit vulnerabilities in CI/CD pipelines to execute unauthorized code - whether that’s potentially compromising credentials, modifying production artifacts, or establishing persistent backdoors.

In this blog post, we dive deep into the anatomy of PPE, drawing from real-world incidents and outlining actionable best practices to defend your pipelines against this insidious attack method.

Understanding the types of PPE

At its core, PPE occurs when an attacker manipulates files that influence how CI/CD pipelines operate. This can be the pipeline configuration itself, or indirectly, any file referenced by it - like build scripts, Makefiles, or test configurations.

There are three primary flavours of PPE:

  • Direct PPE (D-PPE): The attacker modifies the CI configuration file directly.
  • Indirect PPE (I-PPE): The attacker alters files referenced by the CI config. (scripts, Makefiles, tests).
  • Public PPE (3PE): Attacks via public or shared repositories consumed by the pipeline.

The crux of the problem? Pipelines often run unreviewed code - especially when triggered by events such as pull requests or commits to arbitrary branches. If this code is malicious, the pipeline executes it with all the power and trust granted to the CI system.

D-PPE: Direct Poisoning in Action

In a Direct PPE attack, adversaries manipulate the CI/CD configuration file. For example, this simple GitHub Actions build workflow might look benign:

But with write access or an accepted pull request, an attacker can inject malicious commands. In this case, they are piping out the environmental variables of access key and secret key to a remote server in Base64 format to evade detection:

A seemingly simple change can exfiltrate AWS credentials stored in GitHub secrets to an attacker’s server, granting them access to your production cloud environment.

D-PPE Case Study: Teleport

In 2021, Teleport (a well-known open-source, infrastructure identity platform) identified a critical vulnerability in its CI/CD infrastructure, which relied on Drone CI and Kubernetes. The issue stemmed from the use of privileged Docker-in-Docker (DIND) containers. A malicious pull request could exploit this setup to escape the container sandbox and access secrets from neighboring pods. Some of these secrets included credentials tied to Teleport’s production environment. 

Although no breach ultimately occurred, the exposure highlighted a dangerous architectural flaw: the compromised Drone instance was responsible for both internal and external CI/CD workflows. As a result, the stolen secrets had the potential to impact a wide range of critical assets, including release artifacts for Teleport and Gravity, backend services for Teleport Cloud, legacy billing systems, and private GitHub repositories.

This incident could also be categorised as a Direct-3PE attack since it allowed attackers from the public internet to create a pull request in a public Github repository linked with the Drone CI pipeline, which allowed the adversary to modify the CI conf file that executed the malicious pipeline.

I-PPE: The Subtle Art of Indirect Poisoning

In some setups, attackers may not have the ability to change the CI config itself - but they can alter referenced files like Makefiles, test scripts, or shell scripts. This is Indirect PPE.

Consider a Jenkins pipeline where the Jenkinsfile is fetched from a protected branch, but the Makefile lives in the pull request:

During the build stage, AWS credentials are loaded as environment variables. When the make build command runs, the attacker’s malicious command sends the entire environment (including credentials) to the remote server.

I-PPE Case Study: Amazon Web Services

In 2021, a public AWS-operated website was exposed to I-PPE. The buildspec.yml referenced a deploy.sh file that attackers could manipulate via a pull request. Due to insufficient validation, the pull request triggered CodeBuild, which ran deploy.sh with deployment privileges. The attacker uploaded a test file directly to production - demonstrating full deployment access. 

Why PPE Is a Critical CI/CD Security Risk?

PPE attacks are particularly dangerous because CI/CD pipelines often run with high privileges. A successful attack may lead to:

  • Code tampering: Attackers may implant malware in production artifacts.
  • Credential theft: Environment variables and secret stores are frequent targets.
  • Persistent backdoors: PPE can be a foothold for long-term espionage or control.
  • Infrastructure compromise: Privileged access to cloud resources, databases, or internal networks.

How to Protect Your CI/CD Pipeline from PPE

The good news? While PPE is a serious threat, it’s far from unstoppable. With the right strategy, you can significantly reduce the risk. Here’s how to think about building a safer CI/CD pipeline:

Start by isolating the untrusted stuff.
Not all code deserves full access to your build environment - especially code coming from forks or pull requests submitted by external contributors. Treat these with caution. Set up isolated build environments where unreviewed code can run safely, and ensure that any IAM roles tied to these builds are stripped down to the bare minimum. Above all, never expose secrets or sensitive credentials to jobs triggered by external PRs.

Take your CI config seriously.
Your pipeline configuration files are just as sensitive as application code (maybe more so). Store them in protected branches, enforce peer reviews for any changes, and consider keeping your build logic (like scripts or Makefiles) in a separate, locked-down repository. A poisoned pipeline often starts with a poisoned config file. Don’t let that door swing open.

Don’t hand out repo access like candy.
If users don’t absolutely need write access, don’t give it to them. Protect your branches, especially the ones that trigger CI workflows. Keep an eye on changes to build-related files, and make it someone’s job to monitor for anything suspicious. This is basic hygiene.

Be stingy with credentials.
Credentials should never be treated as default baggage in your builds. Inject them only when absolutely necessary, and scope them as tightly as possible. Even better: rotate your secrets regularly and audit their usage. That way, even if something does leak, the blast radius is small.

Finally, think twice about what triggers your pipeline.
Do all pull requests really need to kick off a full build and deployment? Probably not. Instead of letting every PR fire off a pipeline, add a manual approval step, or use automated policies to screen them first. This gives you a chance to spot anything fishy before it gets too far downstream.

PPE in CI/CD Pipelines is Real. And It’s Here.

PPE isn’t some theoretical risk - it’s a very real, rapidly evolving threat. As breaches at organizations like AWS and Teleport have shown, even experienced engineering teams can be blindsided when trust assumptions in CI/CD systems are exploited.

Open-source projects are especially vulnerable. By design, public repositories invite contributions from anyone, anywhere - making them prime targets for Public PPE (or 3PE) attacks. When these public pipelines run unreviewed code on shared CI infrastructure, they can inadvertently expose internal secrets and compromise sensitive assets from private projects.

But this isn’t a hopeless situation. By enforcing clear trust boundaries, hardening build environments, and embracing Zero rust tooling like Cloudsmith, teams can make PPE-style attacks significantly harder to pull off. As your software delivery grows more complex, securing your CI/CD pipeline requires far more considerations than just the potential pipeline poisoning. That’s why the OWASP Top 10 for CI/CD systems was published.

If you found this content helpful and want to dive deeper into securing your CI/CD pipelines, be sure to check out our free Cloudsmith eBook on the OWASP Top 10 for CI/CD systems - download it here.

Get our next blog straight to your inbox