100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
DevSecOps & Security Automation
25 minadvanced

Pipeline poisoning attacks and runner isolation

Pipeline poisoning is a class of attack that targets the build process itself rather than the finished application. By tampering with build scripts, dependencies, or the runners that execute them, an attacker can inject malicious code into legitimate artifacts that are then signed, distributed, and trusted downstream. This lesson examines the main poisoning techniques and explains why isolating build runners is the single most effective defence against them.

Analogy🏏Cricket
🎮 Think of it like gaming: the smartest cheaters do not hack your account, they poison the game's update server, so the next official patch every player downloads is already tampered — and because it arrives through the trusted channel, nobody suspects it. Pipeline poisoning works the same way: instead of attacking the finished application, an attacker tampers with build scripts, dependencies, or the runners that execute them, injecting malicious code into legitimate artifacts that are then signed and trusted downstream. Because the poison rides the trusted build channel, it is devastating and quiet. This reveals isolating the runners that assemble your software as the single most effective defence.

A well-documented technique is Poisoned Pipeline Execution, where an attacker submits a pull request that modifies the CI configuration or a build step, then relies on the pipeline running that untrusted change with privileged access. If the platform executes pull-request workflows with secrets in scope, the malicious step can steal credentials or alter outputs. Related attacks poison a shared dependency cache or a build tool so that every subsequent build silently inherits the compromise.

Analogy🏏Cricket
🎬 Think of it like movies: a saboteur does not storm the film set — they slip a rewritten page into the shooting script, and the whole crew dutifully films the scene the intruder authored. Poisoned Pipeline Execution is that swapped page: an attacker submits a pull request that modifies the CI configuration or a build step, then relies on the pipeline running it with privileged access. If the platform executes pull-request workflows with secrets in scope, the malicious step can steal credentials or alter outputs. Related attacks poison a shared dependency cache or build tool so every later build silently inherits it. This reveals the build's trust in submitted changes as the opening an attacker exploits.

Under the hood, most poisoning succeeds because runners are reused and over-privileged. A persistent runner that serves many jobs may retain secrets, cached files, or malware from an earlier compromised build, contaminating everything that follows. A runner shared across projects lets one team's malicious job read another's credentials. Ephemeral, single-tenant runners that are created fresh for each job and destroyed afterward remove this persistence, collapsing the window in which poison can spread.

Analogy🏏Cricket
🎵 Think of it like music: a recording studio that never wipes the mixing desk between clients lets one band's settings, samples, and stray noise bleed into the next session's master — and a desk shared across rival bands leaks one group's unreleased tracks to another. Persistent build runners do exactly this: a runner serving many jobs can retain secrets, cached files, or malware from an earlier compromised build, contaminating everything after, and a shared runner lets one team's malicious job read another's credentials. Ephemeral, single-tenant runners are a freshly reset desk for every session, created new and destroyed afterward. This reveals runner persistence as the medium poison travels through.
text
# Isolation controls that break poisoning chains
- Ephemeral runners: fresh VM per job, destroyed after use (no residue)
- Single-tenant:     one project per runner; no shared secret access
- No secrets on PRs: untrusted pull-request jobs run without credentials
- Pin & verify:      dependencies by digest; actions by commit SHA
- Egress control:    restrict what a build job can reach on the network
Analogy🏏Cricket
🏏 A reused, over-privileged runner is like one shared bat passed between every batsman all season — tamper with it once and every innings after is compromised, and nobody knows when the crack appeared. An ephemeral runner is a brand-new bat for each batsman, inspected and then retired. Poison one and the damage stops at a single innings, because the next player never touches that bat again. Giving every innings its own inspected bat, rather than circulating one shared blade all season, is exactly how a fresh runner per job denies poison anywhere to persist. This reveals disposability, not vigilance alone, as what collapses the window an attacker needs.

Best practice isolates aggressively and denies untrusted code any privilege. Run each job on an ephemeral, single-tenant runner, withhold secrets from workflows triggered by outside pull requests until a maintainer approves them, and pin dependencies and actions to immutable digests so a swapped version cannot slip in. Restrict each runner's outbound network access so a poisoned step cannot exfiltrate stolen secrets, and monitor build behaviour for anomalies such as unexpected outbound connections.

Analogy🏏Cricket
📷 Think of it like photography: a careful darkroom is ruthless about isolation — one sheet per tray, fresh chemistry each time, the door light-sealed so no stray exposure ruins the print. Harden runners with the same discipline: run each job on an ephemeral, single-tenant runner, withhold secrets from workflows triggered by outside pull requests until a maintainer approves them, and pin dependencies and actions to immutable digests so no swapped version slips in. Restrict each runner's outbound network so a poisoned step cannot exfiltrate what it steals, and watch build behaviour for anomalies. This reveals layered isolation as the darkroom discipline that keeps every build clean.

In the real world, several high-profile supply-chain incidents traced back to a build environment that trusted untrusted input or reused a contaminated runner. Teams that had already adopted ephemeral, isolated runners and withheld secrets from external pull requests found those same attack attempts fizzling harmlessly, because the malicious job ran in a disposable sandbox with no credentials, no shared state, and no network path to carry anything out.

Analogy🏏Cricket
✈️ Think of it like travel: seasoned travellers carry almost nothing valuable through a risky transit — a locked, near-empty bag and no cash on show — so a pickpocket finds nothing worth taking and no way home. Several high-profile supply-chain incidents traced back to a build environment that trusted untrusted input or reused a contaminated runner. Teams that had already adopted ephemeral, isolated runners and withheld secrets from external pull requests watched the same attacks fizzle harmlessly: the malicious job ran in a disposable sandbox with no credentials, no shared state, and no network path to carry anything out. This reveals isolation as leaving the attacker nothing to steal and nowhere to send it.
  • Pipeline poisoning attacks the build process to inject code into trusted artifacts.
  • Poisoned Pipeline Execution abuses untrusted PRs that run with privileged access.
  • Reused, over-privileged runners let poison persist and spread across builds.
  • Ephemeral, single-tenant runners destroy state between jobs and stop the spread.
  • Withhold secrets from external PRs and restrict runner egress to block exfiltration.
Lesson 11 of 35
0% complete