Join our Newsletter — 33% off our NHI Course

What is the difference between artifact poisoning and code injection in CI/CD pipelines?

Artifact poisoning changes what later pipeline steps execute by altering files or archives that those steps trust. Code injection changes what the runner executes by manipulating untrusted input that is embedded directly into shell commands or scripts. Both can lead to secret exposure or unauthorized actions, but one attacks the artifact boundary while the other attacks command construction.

Artifact poisoning shifts trust, code injection shifts execution

In a CI/CD pipeline, artifact poisoning targets what downstream stages trust as already-built output. The attacker alters a file, package, container image, or archive so a later step processes malicious content under the assumption that the artifact is legitimate. code injection targets the command boundary instead, where untrusted data is concatenated into shell commands, scripts, or task arguments and then executed by the runner.

The distinction matters because the defensive failure is different. With artifact poisoning, the pipeline may be structurally sound at execution time but still consume a compromised build output. With code injection, the runner itself is tricked into executing attacker-controlled syntax, often before the artifact even exists. A useful way to think about it is boundary choice: artifact trust versus command construction.

Both patterns can arise from poor input handling, weak provenance, or overly broad pipeline permissions, but they are not the same failure mode. Artifact poisoning usually succeeds when a stage treats upstream output as trusted without verifying origin or integrity. Code injection succeeds when a pipeline interpolates variables, branch names, commit messages, or PR content into shell context without strict quoting or escaping.

For teams reviewing CI/CD risk, this is why supply-chain integrity controls and command-safety controls are complementary, not interchangeable. A pipeline can have strong script hygiene and still be vulnerable if it downloads or passes forward unverified artifacts. It can also verify artifacts and still be exploitable if a runner executes unsanitized input. The threat surface changes depending on whether the attacker is shaping data that will be consumed later or shaping the command text that runs now.

Where the attack path usually differs in practice

Artifact poisoning tends to exploit trust relationships between stages. Common examples include tampering with build outputs, dependency packages, release bundles, caches, or generated artifacts so later jobs deploy or test malicious content. That makes integrity and provenance the core concern, especially when downstream systems assume that a file produced by an earlier stage is safe by default.

Code injection is usually more immediate. The runner executes a command, script, or template that includes attacker-influenced text, and the shell interprets characters such as separators, substitutions, or redirections as instructions. The most important question is not whether the input was “allowed” in a general sense, but whether it was ever permitted to become executable syntax. SLSA is relevant here because build provenance and artifact integrity are exactly what poisoning attempts to undermine.

In real pipelines, the two can chain together. A poisoned artifact may later be unpacked, parsed, or invoked in a way that leads to execution. Likewise, code injection may be used to modify a build output that then persists as an artifact. Even so, the control focus should stay separate: verify what is handed off between jobs, and separately prevent untrusted text from becoming executable instructions.

That separation is also why detection differs. Artifact poisoning often shows up as unexpected changes in hashes, signatures, dependency contents, or build provenance. Code injection often shows up as anomalous shell metacharacters, unusual argument expansion, or commands that reference attacker-controlled fields. The first is an integrity and provenance problem, the second is a command-construction problem.

Standards & Framework Alignment

This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.

OWASP Non-Human Identity Top 10 and MITRE ATT&CK address the attack and risk surface, while NIST CSF 2.0 and CIS Controls v8 set the governance and control requirements practitioners need to meet.

Framework Control / Reference Relevance
NIST CSF 2.0 PR.DS — Data Security Artifact poisoning is an integrity problem for data and build outputs crossing pipeline stages.
PR.IP — Information Protection Processes and Procedures CI/CD poisoning and injection both depend on weak pipeline handling procedures and unsafe defaults.
Recommendation — Protect artifact integrity with hashing, signing, and verified retrieval at each pipeline handoff. Harden pipeline procedures for artifact verification, input handling, and release controls.
CIS Controls v8 16 — Application Software Security CI/CD command injection is a software security failure in build and delivery automation.
3 — Data Protection Artifact poisoning alters trusted build data and requires integrity-focused protection.
Recommendation — Eliminate command interpolation from pipeline scripts and validate all externally influenced inputs. Protect build artifacts with integrity checks, secure storage, and controlled transfer paths.
OWASP Non-Human Identity Top 10 NHI-01 — Secrets and Credential Management CI/CD compromise often exposes secrets when poisoned artifacts or injected commands run in pipelines.
Recommendation — Rotate and isolate secrets used by CI/CD jobs so a compromised step cannot reuse them broadly.
MITRE ATT&CK T1059 — Command and Scripting Interpreter Code injection in CI/CD commonly abuses shell or script interpreters on the runner.
T1552 — Unsecured Credentials Both attack types can expose credentials that pipeline jobs can access during execution.
T1195 — Supply Chain Compromise Artifact poisoning is a supply-chain compromise of trusted build or release outputs.
Recommendation — Hunt for command injection patterns wherever pipeline jobs construct shell or script commands from input. Reduce credential exposure in pipelines and monitor for secrets access after suspicious job execution. Validate build provenance and detect tampering in artifacts before downstream consumption.

Practitioner Guidance

What to verify: Treat any artifact that crosses a stage boundary as untrusted until provenance or integrity checks prove otherwise. At the same time, review every place a pipeline builds a shell command from external input, including branch names, PR titles, commit messages, file paths, and environment variables.

Decision rule: If the issue is “who altered the artifact and can we trust it,” focus on artifact provenance, signing, and verification. If the issue is “did the runner execute attacker-controlled text,” focus on command quoting, argument handling, and eliminating shell interpolation where possible.

Common mistake: Teams often harden only one side, for example by adding artifact hashes while still allowing unescaped inputs in scripts, or by sanitizing commands while trusting unsigned build outputs. That leaves a gap large enough for a full pipeline compromise.

Practitioner takeaway: Artifact poisoning and code injection are different because they attack different trust boundaries, so the right control set must protect both the handoff between stages and the syntax the runner executes.