Poisoned Pipeline Execution
This detection identifies adversaries attempting to poison CI/CD pipelines through direct modification of CI configuration files, injection of malicious code into pipeline-referenced build artifacts, or exploitation of fork-based pull request workflows that expose pipeline secrets. Detections span three attack vectors: (1) Direct pipeline execution — changes to CI config files (e.g., .github/workflows, .gitlab-ci.yml, Jenkinsfile) containing suspicious commands such as credential exfiltration via curl/wget, base64-encoded payloads, or environment variable dumping; (2) Indirect pipeline execution — modifications to Makefiles, linters, test suites, or build scripts that are invoked by trusted CI configurations; (3) Public pipeline execution — fork-based pull requests targeting pull_request_target workflows or injecting malicious branch names that are processed as trusted inputs by pipeline steps. Detection coverage includes Azure DevOps audit logs, GitHub audit log events, and process telemetry from CI runner hosts.
let CIConfigFiles = dynamic([".github/workflows", ".gitlab-ci.yml", "Jenkinsfile", ".circleci/config", "azure-pipelines.yml", "bitbucket-pipelines.yml", ".travis.yml", "cloudbuild.yaml"]);
let SuspiciousTerms = dynamic(["curl ", "wget ", "base64 -d", "base64 --decode", "printenv", "env |", "| base64", "exfil", "ngrok", "burpcollab", "interactsh", "webhook.site", "requestbin", "pipedream", "SECRET", "TOKEN", "API_KEY", "AWS_", "GITHUB_TOKEN", "CI_JOB_TOKEN"]);
union isfuzzy=true
(
AzureDevOpsAuditing
| where TimeGenerated > ago(24h)
| where OperationName in (
"Git.Push",
"Git.RefUpdateBatch",
"Pipeline.PipelineModified",
"Build.DefinitionModified",
"Build.DefinitionCreated"
)
| extend DataStr = tostring(Data)
| where DataStr has_any (CIConfigFiles) or DataStr has_any (SuspiciousTerms)
| extend
Actor = ActorUPN,
Platform = "AzureDevOps",
OperationType = OperationName,
SourceIP = IpAddress,
ProjectContext = ProjectName
| project TimeGenerated, Actor, Platform, OperationType, SourceIP, ProjectContext, DataStr
),
(
GitHubAuditLog
| where TimeGenerated > ago(24h)
| where Action in (
"workflows.created",
"workflows.updated",
"git.push",
"protected_branch.update_allow_force_pushes",
"repo.create"
)
| extend DataStr = tostring(Data)
| where DataStr has_any (CIConfigFiles) or DataStr has_any (SuspiciousTerms)
| extend
Actor = Actor,
Platform = "GitHub",
OperationType = Action,
SourceIP = coalesce(IPAddress, "Unknown"),
ProjectContext = tostring(Data.repo)
| project TimeGenerated, Actor, Platform, OperationType, SourceIP, ProjectContext, DataStr
)
| extend RiskScore = case(
DataStr has_any ("base64 -d", "base64 --decode", "interactsh", "ngrok", "webhook.site", "burpcollab"), 95,
DataStr has_any ("printenv", "env |", "AWS_SECRET", "GITHUB_TOKEN", "CI_JOB_TOKEN"), 85,
DataStr has_any ("curl ", "wget ", "| base64", "SECRET", "API_KEY"), 70,
50
)
| where RiskScore >= 70
| sort by RiskScore desc, TimeGenerated desc Data Sources
Required Tables
False Positives
- Legitimate DevOps engineers updating pipeline definitions to add new build steps or integrations — validate against change management tickets
- Authorized security scanning tools (Snyk, Dependabot, GitHub Advanced Security) modifying workflow files during automated PR creation
- Infrastructure-as-code pipelines that legitimately use curl/wget to download build dependencies or SDKs from trusted artifact registries
- Developers experimenting with pipeline debugging steps that temporarily echo environment context — common during onboarding
- Automated dependency update bots (Renovate, Dependabot) modifying workflow files or build scripts as part of their normal operation
References (5)
- https://attack.mitre.org/techniques/T1677/
- https://owasp.org/www-project-top-10-ci-cd-security-risks/CICD-SEC-04-Poisoned-Pipeline-Execution
- https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
- https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions
- https://unit42.paloaltonetworks.com/github-actions-supply-chain-attack-2025/
Unlock Pro Content
Get the full detection package for T1677 including response playbook, investigation guide, and atomic red team tests.