Common CI/CD Attack Paths

Attackers do not need production shell when the pipeline can deploy for them. Learn the common CI/CD attack paths across secrets, runners, workflows, artifacts, and environments.

Common CI/CD Attack Paths illustration
On this page17 sections

CI/CD systems are trusted automation with access to source code, secrets, artifacts, cloud roles, deployment environments, and production clusters. That makes them attractive targets. An attacker does not need direct production access if the pipeline can build, sign, and deploy for them.

This guide explains common CI/CD attack paths and the controls that reduce blast radius.

Attack Path 1: Poisoned Pull Request Workflow

A pull request from an untrusted branch can change code, tests, scripts, and sometimes workflow files. If that workflow receives secrets or privileged tokens, the attacker can exfiltrate credentials or modify build output.

Controls:

  • Do not expose deployment secrets to untrusted pull request workflows.
  • Separate validation workflows from privileged release workflows.
  • Require approval before running workflows from first-time contributors.
  • Pin actions and tools where the risk justifies it.

Attack Path 2: Long-Lived Secrets in CI

Static cloud keys, registry tokens, SSH keys, and kubeconfigs are often stored as CI secrets. Once leaked, they may work outside the pipeline and outside the intended job.

Use OIDC federation when possible. The CI platform should request a short-lived token scoped to the repository, branch, environment, and workflow. Cloud IAM policy can then decide whether that run is allowed to deploy.

Attack Path 3: Compromised Runner

Self-hosted runners are powerful but dangerous when they run untrusted jobs. A runner may keep workspace files, Docker layers, credentials, network access, or cached artifacts between jobs if it is not isolated correctly.

High-risk workloads should use ephemeral runners. At minimum, isolate runner groups by trust level, clean workspaces aggressively, restrict network access, and avoid sharing deployment runners with pull request validation.

Attack Path 4: Dependency Confusion and Build Tool Abuse

Builds often fetch dependencies, plugins, base images, scripts, and tools. If package names, registries, versions, or checksums are not controlled, a malicious dependency can execute during install or build.

Controls include private registry configuration, lockfiles, dependency review, checksum verification for downloaded tools, and avoiding curl-to-shell install steps in trusted pipelines.

Attack Path 5: Artifact Replacement

If attackers can overwrite an image tag, package, or release artifact after review, production may deploy something different from what was approved. Mutable tags such as latest make this worse.

Use immutable digests, restricted registry permissions, provenance, image signing, environment approvals, and deployment policy that verifies the artifact identity.

Attack Path 6: Overpowered Environment Permissions

Many pipelines use the same credentials for staging and production. Some allow any branch to deploy to sensitive environments. Others grant broad cloud permissions because least privilege was too slow during setup.

Use environment-specific policies, branch restrictions, manual approvals for sensitive changes, and role separation between build, publish, and deploy steps.

CI/CD Defense Checklist

  • Map every workflow that can publish or deploy artifacts.
  • Remove static cloud keys where OIDC federation is supported.
  • Separate untrusted PR workflows from trusted release workflows.
  • Use ephemeral or strongly isolated self-hosted runners.
  • Pin critical actions, base images, and tool downloads.
  • Generate provenance and sign release artifacts.
  • Deploy by immutable digest, not mutable tags.
  • Enforce production admission policy for signed and trusted artifacts.

Attack Path Flow Diagram

CI/CD attacks usually work because the pipeline is trusted to do what humans cannot do manually: fetch secrets, build artifacts, and deploy. The attacker only needs to influence one trusted step.

High-Risk Workflow Patterns

The most dangerous pipeline designs combine untrusted code execution with trusted credentials. Fork pull requests, dependency install scripts, generated build steps, and workflow changes are all code execution paths. If those paths can access secrets or write artifacts that production trusts, they become deployment paths for attackers.

Pattern Why it is risky Safer design
Fork PR runs with secrets Untrusted code can exfiltrate credentials. Run untrusted PR checks without secrets; deploy only after trusted review.
Workflow file changes auto-run Attacker changes the pipeline before the pipeline protects itself. Require code owner review for workflow and IaC paths.
Long-lived cloud keys in CI Stolen key remains useful after the job ends. Use OIDC federation with short-lived scoped credentials.
Mutable release tags A trusted tag can be replaced with a malicious artifact. Deploy by digest and prevent overwrite of release artifacts.

Example: Split Build and Deploy Trust

A safe pipeline often has two trust levels. The first level runs tests on untrusted code without secrets. The second level deploys only reviewed code from protected branches. This is less convenient than one pipeline that does everything, but it makes the trust boundary visible.

# Safer pipeline shape
pull_request:
  permissions: read-only
  secrets: none
  actions: test, lint, build-untrusted

main_branch_after_review:
  permissions: scoped
  credentials: short-lived OIDC role
  actions: build, sign, attest, deploy

Detection Signals

CI/CD security is not only prevention. You should alert on unusual workflow edits, new secrets, new self-hosted runners, unexpected outbound network calls during build, artifact overwrites, deployments outside normal windows, and new cloud roles assumed by CI. These signals often catch misuse faster than vulnerability scanners.

Runner Isolation Model

Runners are execution environments, so treat them like production infrastructure. A hosted runner, a self-hosted runner, and a long-lived build machine have different risk profiles. The central question is whether untrusted code can persist, read credentials, reach internal networks, or influence a later trusted build.

Self-hosted runners are useful for private networks, large builds, or specialized hardware, but they require stronger isolation. If an untrusted pull request can run on a self-hosted runner with access to internal systems, the runner becomes a bridge from the internet into your environment. Use ephemeral runners, network segmentation, clean workspaces, and strict workflow routing.

Runner type Main risk Mitigation
Hosted ephemeral runner Workflow permissions and exposed secrets. Least privilege job permissions, no secrets for untrusted code, OIDC roles.
Persistent self-hosted runner State persists between jobs and can expose future builds. Avoid for untrusted code, clean workspace, rotate credentials, isolate network.
Ephemeral self-hosted runner Provisioning image or bootstrap script compromise. Harden images, patch frequently, restrict metadata and internal network access.

Threat Modeling a Pipeline Change

Before approving a pipeline change, ask what new authority it grants. Does it add a secret? Does it change who can deploy? Does it install dependencies from a new registry? Does it run on a privileged runner? Does it upload artifacts to a trusted location? Does it change the permissions block? Those are security changes even if the file is called CI configuration.

pipeline_review_questions:
  - "Can this workflow run on untrusted input?"
  - "Can it read secrets or assume cloud roles?"
  - "Can it publish packages, images, or release assets?"
  - "Can it deploy or modify infrastructure?"
  - "Can it change another workflow or generated artifact?"
  - "Is the runner isolated from internal services?"

How to Handle Tag and Release Attacks

Tags feel stable, but many systems treat mutable tags as trusted release identifiers. If an attacker can move a tag, overwrite a package, or push a new image to an existing tag, consumers may deploy attacker-controlled code while believing they are using a known release. Production systems should prefer immutable digests and should protect release tags from modification.

For containers, deploy by digest where possible. For packages, enforce registry permissions, provenance, and version immutability. For Git tags, protect release tag patterns and require signed or reviewed release workflows when the organization needs that level of assurance. The goal is to make a release artifact a stable object, not a name that can quietly point somewhere else.

Practical Review Flow for Existing Pipelines

If you already have dozens of workflows, do not try to redesign them all in one pass. Start by listing workflows that can deploy, publish packages, push images, assume cloud roles, or modify infrastructure. Those workflows are the trust boundary. Read them line by line and mark where they accept input, where they install dependencies, where they read secrets, and where they write artifacts.

Then rank the risky paths. A lint workflow with no secrets is usually less urgent than a deployment workflow with a broad cloud role. A workflow that runs only on the protected main branch is different from one that runs on fork pull requests. A self-hosted runner connected to internal networks deserves more attention than an ephemeral hosted runner running unit tests. This ranking keeps the work practical and prevents security review from becoming a spreadsheet nobody finishes.

The final step is enforcement. Good guidance is not enough if the old pattern remains easy. Add repository rules for workflow files, set default job permissions to read-only, require environment approvals for production, and make reusable secure workflow templates the default for new services. That is how teams move from awareness to durable control.

Sources and Further Reading

Share this article

Stuck on implementation?

Get private, 1-on-1 help with system design, performance, scaling, or any technical challenge.

Book a Session

Related Production Resources

Course

Free learning tracks

Turn this guide into a structured production engineering path.

Lab

Interactive engineering labs

Practice the same ideas through scenario-based simulators.

Reference

Production cheatsheets

Keep the operational commands and checks nearby.

Glossary

Key terms

Review the vocabulary behind the architecture.

Discussion

Questions, corrections, or production notes? Add them here so other learners can benefit.

Continue Reading

Related practical guides from the same production engineering path.

DevOps 8 min read

Modern Data Platforms Compared: Snowflake, Databricks, BigQuery, and e6data

Compare Snowflake, Databricks, BigQuery, and e6data through the production decisions that matter: storage, compute, governance, table formats, cost control, and workload fit.

Data Engineering Snowflake
DevOps 10 min read

Why Spark Jobs Become Slow: Shuffle, Skew, Partitions, and Memory

Spark jobs usually slow down for predictable reasons: too much shuffle, skewed keys, bad partition sizing, expensive file layouts, and memory pressure. Learn how to debug each one.

Spark Data Engineering