SuperAPI AI Directory

cicd-pipeline-attack

General & other

View repository

Updated 10-16 04:57

About this skill

CI/CD Pipeline and Supply Chain Attack Methodology

CI/CD systems are core infrastructure of modern software engineering—they have read and write access to code repositories, hold deployment credentials for cloud platforms, and can directly modify production environments. Once a pipeline is compromised, an attacker can simultaneously gain code control, Secrets access, and cloud environment penetration capability, with an impact scope far exceeding the compromise of a single server.

This skill organizes CI/CD attack methodology in the form of a decision tree. For detailed technical methods for each platform, please refer to the corresponding reference documents.

In-depth Reference

After identifying a specific platform, load the corresponding reference document to obtain complete attack technical details:

Phase 0: CI/CD System Identification

When the following identifying files are found in the target code repository or infrastructure, the corresponding CI/CD platform can be determined:

Identifying File/Feature CI/CD Platform Next Step
.github/workflows/*.yml GitHub Actions → Phase 2 PPE + refer to github-actions-abuse.md
Jenkinsfile or /script console Jenkins → Phase 4 Jenkins specialized + refer to platform-specific.md
.gitlab-ci.yml GitLab CI → Phase 2 PPE + refer to platform-specific.md
.circleci/config.yml CircleCI → Phase 2 PPE + refer to platform-specific.md
azure-pipelines.yml Azure DevOps → Phase 2 PPE + Service Connection Secret extraction
.drone.yml Drone CI → Phase 2 PPE + Self-hosted Runner check
.buildkite/*.yml Buildkite → Phase 2 PPE + Agent cloud/K8s permission check
atlantis.yaml + Webhook Atlantis → Phase 4 Atlantis specialized
*.tf + Terraform Cloud Terraform Cloud → Phase 4 Terraform specialized
serverless.yml Serverless Framework → refer to platform-specific.md
docker-compose.yml + CI trigger Docker Build → Check build context leakage
Airflow DAGs / Concourse pipeline Airflow / Concourse → refer to platform-specific.md

Quick identification tips:

  • After cloning the repository, search for configuration files: look for Jenkinsfile、.github/workflows、.gitlab-ci.yml、.circleci、atlantis.yaml
  • Check Webhook configuration: Webhook URLs expose the CI/CD service type and internal network addresses
  • Enumerate CI/CD service ports: Jenkins defaults to 8080, Atlantis defaults to 4141, GitLab Runner 8093

Phase 1: VCS Attack Surface

Before entering pipeline attacks, VCS (version control system) itself is an important attack surface.

1.1 Code Leakage

Common sources of sensitive information in code repositories:

  • Git history: Deleted keys/credentials may still be in the commit history (git log -p search all branches)
  • Public repositories: Use GitHub Dork to search organization name + keywords (password、secret、token、AWS_)
  • Deleted Fork data: Commit data in deleted forks on GitHub can still be accessed via commit hash
  • Internal repository exposure: Fork data from before a private repository became public can be brute-forced via short SHA-1 enumeration

1.2 Branch Protection Bypass

Branch protection is a key line of defense against malicious code being merged, but there are multiple ways to bypass it:

Bypass scenario Condition Attack method
Insufficient approvals Control multiple accounts Use another account to approve your own PR
GITHUB_TOKEN self-approval Actions has write permissions Approve a PR via GITHUB_TOKEN in Actions
Approval not invalidated after push "dismiss on push" not enabled First submit legitimate code to obtain approval, then push malicious code
CODEOWNERS misconfiguration Incorrect file format GitHub does not report an error but CODEOWNERS protection becomes ineffective
New branch unprotected Use wildcard * but there is a delay When a new branch is created, branch protection has not yet taken effect, and the first push can trigger Actions
Administrator exemption Administrators not included in the rules Administrators can directly bypass all branch protection
PR hijacking Can modify others' PRs Inject malicious code into someone else's PR and then approve and merge it yourself

1.3 Webhook abuse

  • No Secret verification: An attacker can forge Webhook requests to trigger the pipeline
  • Secret exposed in URL: The Secret is attached in URL parameters and is easily logged
  • IP allowlist bypass: Creating an account on GitHub/GitLab and configuring a Webhook is enough to send requests to Jenkins/Atlantis within the allowlist
  • Bitbucket Cloud: Webhook Secret is not supported, so it can only rely on the IP allowlist

Phase 2: PPE -- Poisoned Pipeline Execution

PPE is the core framework of CI/CD attacks. Attackers "poison" the pipeline by modifying CI configuration files or their dependency files, causing it to execute malicious commands.

PPE determination decision tree

是否能写入/修改 CI 配置文件(workflow yml / Jenkinsfile / .gitlab-ci.yml)?
├── 是 → D-PPE(直接毒化)
│   ├── 能直接推送到触发分支 → 最简单路径
│   └── 需要 PR → 检查 PR 是否触发流水线
│
├── 否,但能修改 CI 配置依赖的文件?
│   ├── Makefile / build.sh / package.json / requirements.txt → I-PPE(间接毒化)
│   ├── Terraform .tf 文件 → I-PPE via external data source
│   └── Dockerfile → I-PPE via build context
│
└── 否,且无仓库写权限?
    └── 3PE(第三方毒化)
        ├── 能否提交外部 PR? → pull_request 触发器
        ├── PR 标题/描述是否被注入到 shell 命令? → Context Script Injection
        └── 能否通过 issue/comment 触发? → issue_comment 触发器

D-PPE(Direct PPE)

The attacker directly modifies the CI configuration file. This is the most direct attack path:

  • Prerequisite: Has repository write permission, or can trigger a pipeline that uses the PR branch configuration through a PR
  • Target file:.github/workflows/*.yml、Jenkinsfile、.gitlab-ci.yml、.circleci/config.yml
  • Key condition: Some platforms (such as GitHub Actions' pull_request trigger) use the workflow version submitted by the PR author—this means the attacker's modifications will be executed

I-PPE(Indirect PPE)

The attacker does not modify the CI configuration file itself, but instead modifies files that the CI configuration depends on:

  • Build script:Makefile、build.sh、package.json 's scripts field
  • Dependency file:requirements.txt、package-lock.json(supply chain injection)
  • IaC configuration:Terraform .tf in the file external data source or local-exec provisioner
  • Docker build: Control the Dockerfile or build context path

The limitation of I-PPE is that the attacker can only access Secrets that the pipeline originally loads, and cannot declare new Secret references through configuration.

3PE(Third-Party PPE / Public PPE)

External attackers without repository write permission trigger the pipeline in the following ways:

Context Script Injection (most common):

When the CI configuration uses ${{ github.event.pull_request.title }} and other user-controllable expressions in run: When concatenating shell commands in a step, an attacker can inject commands via the PR title. GitHub Actions renders the expression before execution, so shell quote escaping cannot prevent it.

Dangerous trigger comparison:

Trigger Secrets access Write permissions Code version used Risk
pull_request None (GITHUB_TOKEN read-only) None PR branch Low (but can upload malicious Artifacts)
pull_request_target Yes Yes Base branch (safe by default) High (extremely dangerous if checkout PR code)
workflow_run Yes Yes Depends on configuration High (often exploited in chains)
issue_comment Yes Yes Base branch High (RCE when combined with checkout PR ref)

pull_request_target fatal misuse:

Although pull_request_target runs in the base branch context (seemingly safe), if the workflow explicitly checks out the PR code (ref: ${{ github.event.pull_request.head.sha }}), the attacker's code executes in an environment with Secrets and write permissions.

Phase 3: Secrets theft and lateral movement

After successfully poisoning the pipeline, the core goal is to steal Secrets and expand outward.

3.1 Secrets extraction methods

Environment variables:

  • env | base64 export all environment variables (base64 encoding can bypass GitHub's log masking)
  • Double base64 encoding further bypasses masking:echo '${{ toJson(secrets) }}' | base64 -w0 | base64 -w0

File system:

  • Temporary script files:/home/runner/work/_temp/*(GitHub Actions stores the rendered script)
  • Process memory:gcore or /proc/<pid>/mem read plaintext Secrets from the Runner.Worker/Runner.Listener processes

When direct exfiltration is not possible:

  • Use GITHUB_TOKEN to create repositories/issues/comments as a data relay
  • Write Secrets to Artifacts and upload them
  • Write to Actions logs (note masking rules)

3.2 CI/CD to cloud environment traversal

CI/CD Runners usually have cloud platform credentials for deployment. These credentials are the bridge from CI/CD to the cloud environment:

Credential source Location Exploitation method
OIDC Token(GitHub → AWS/GCP/Azure) id-token: write permissions Request OIDC Token → AssumeRoleWithWebIdentity
AWS static AK/SK Environment variables or Secrets Refer to the cloud-aksk-exploit skill
GCP Service Account JSON File or environment variable Refer to the gcp-pentesting skill
Azure Service Principal Environment variables Refer to the Azure-related content in the aws-pentesting skill
Terraform Cloud Runner credentials tfc-aws-*/tfc-gcp-* files Directly use CLI to operate cloud resources
Kubernetes kubeconfig ~/.kube/config or mounted SA Token Cluster takeover
Docker Registry Token ~/.docker/config.json Push malicious images

Additional attack surface for Self-hosted Runners:

  • Cloud metadata service (169.254.169.254) → obtain IAM role credentials bound to the instance
  • Internal network lateral movement → Access other internal services
  • Docker API (2375/tcp) → Container escape
  • Kubernetes cluster access → DaemonSet lateral scaling

3.3 Production Environment Takeover

If the pipeline is directly responsible for production deployment:

  • Code tampering: Inject backdoor code into build artifacts
  • Supply chain attack: Tamper with the npm/PyPI package publishing process (steal publish token → publish malicious version)
  • Image poisoning: Modify Docker image layers to inject malicious code
  • IaC tampering: Modify Terraform/CloudFormation configuration to create backdoor resources

Phase 4: Platform-Specific Attacks

4.1 GitHub Actions

GitHub Actions is one of the most widely used CI/CD platforms, with a rich attack surface:

  • Artifact Poisoning: Low-privilege workflow uploads malicious Artifact → High-privilege workflow downloads and executes it
  • Cache Poisoning: Cache shared across workflows lacks trust isolation → Poison scripts/binaries in the cache
  • GITHUB_TOKEN abuse: Merge PR, approve PR, create PR
  • Action Tag hijacking: After an attacker gains write access to an Action repository, force-push a tag to point to a malicious commit
  • AI Agent injection: LLM Agent in CI (Gemini/Claude Code Action) can be controlled by prompt injection

→ Read references/github-actions-abuse.md

4.2 Jenkins

Jenkins' high-privilege characteristics make it a high-value target:

  • Groovy Script Console(/script) → Direct RCE
  • Pipeline creation/modification → Execute arbitrary commands through Jenkinsfile
  • Credential dumping → Groovy script exports all secrets in credentials.xml
  • File read → RCE → Read master.key + hudson.util.Secret → Offline decrypt all credentials → Forge remember-me Cookie

→ Read references/platform-specific.md

4.3 Terraform / Atlantis

The core of IaC tool attacks lies in code as execution:

  • Terraform Plan RCE:external data source or malicious Provider can execute code at the plan stage
  • Terraform Apply RCE:local-exec provisioner executes at the apply stage
  • State file tampering: Write to state file to inject malicious provider → Next plan/apply triggers RCE
  • Atlantis Plan injection: Modify in PR .tf file triggers atlantis plan → RCE on the Atlantis server
  • Atlantis Custom Workflow: When allow_custom_workflows=true ,atlantis.yaml can define arbitrary execution steps
  • Terraform Cloud Speculative Plan: Steal TFC Token → Trigger speculative plan → Execute code on Runner → Obtain injected cloud credentials

→ Read references/platform-specific.md

4.4 Other Platforms Quick Reference

Platform Key attack paths Details
GitLab CI Runner Token theft, shared Runner escape, CI variable injection → platform-specific.md
CircleCI Context Secrets theft, SSH Rerun, project variable import → platform-specific.md
Azure DevOps Service Connection Secret, variable/parameter injection, Runner hijack → platform-specific.md
Drone CI .drone.yml commands injection, Self-hosted Runner cloud/K8s privileges → platform-specific.md
Buildkite .buildkite/*.yml command injection, Agent's cloud/K8s privileges → platform-specific.md
Serverless Framework IAM Role privilege escalation (default AdministratorAccess), Plugin poisoning → platform-specific.md
CloudFlare Workers abuse, Zero Trust bypass → platform-specific.md
Concourse / Airflow Refer to platform-specific.md quick reference table → platform-specific.md

Precautions

Operational security:

  • CI/CD systems usually have complete audit logs—PR creation, workflow execution, and Secrets access are all recorded
  • PRs on GitHub may still be captured by SIEM even after the account is deleted
  • Operations on a Self-hosted Runner may trigger EDR/HIDS alerts
  • During authorized testing, the scope and impact of CI/CD testing should be confirmed with the client in advance

Secrets protection bypass:

  • GitHub Actions log masking only protects rendered output; plaintext still exists in process memory
  • Using base64 encoding or encryption can bypass most automatic masking mechanisms
  • Derived data such as JWT signature values will not be masked

Supply chain attack escalation:

  • After stealing an npm/PyPI publish token, malicious package versions can be published
  • npm's preinstall/postinstall hook executes automatically at install time
  • Python's .pth file executes automatically when the interpreter starts
  • A single CI/CD compromise may cascade to affect the entire supply chain (see the tj-actions/Ultralytics incident)