Wiz disclosed that its autonomous Red Agent — an AI-driven offensive testing system — independently discovered and validated a GitHub Actions vulnerability that was introduced by GitHub Copilot's Autofix feature in a Snowflake repository. The Red Agent then chained that weakness into validated access to sensitive data in Snowflake's internal Jira and mapped the blast radius, all without human operators in the loop.
Read that again: an AI code-generation tool introduced a security defect into a CI/CD pipeline, and an AI red-teaming agent found and exploited it end-to-end. This is the new reality of the software supply chain. The vulnerability itself isn't an exotic memory corruption bug — it's the class of flaw we see constantly in pipeline security reviews: unsafe workflow logic, over-permissive tokens, and untrusted input flowing into privileged automation. What changed is the author (an AI assistant) and the attacker (an AI agent), and the speed at which both operate.
For defenders, the lessons are immediate:
- AI-generated fixes are commits like any other — and need the same (or more) scrutiny. Autofix suggestions can alter workflow files, permissions blocks, and trigger conditions in ways that pass casual review.
- GitHub Actions is a privilege escalation surface. A single misconfigured workflow can hand an attacker GITHUB_TOKEN credentials, OIDC cloud roles, or — as in this case — a pivot path into internal SaaS systems like Jira.
- Autonomous offensive agents are here. Your exposure window is no longer measured in weeks between pentests. Assume continuous, machine-speed probing of anything reachable from a PR trigger.
No CVE has been assigned to this issue; it is a logic/configuration flaw in how an Autofix-generated change interacted with GitHub Actions permissions, not a patched platform bug. The defensive guidance below therefore focuses on detection of the technique class and hardening of your pipelines rather than a version bump.
Technical Analysis
Affected components and platforms
| Component | Exposure |
|---|---|
| GitHub Actions workflows | Any repository where Copilot Autofix (or any AI assistant) can propose changes to .github/workflows/*.yml |
| GitHub Copilot Autofix | Code scanning autofix suggestions that touch CI/CD configuration, permissions blocks, or script steps |
| GITHUB_TOKEN / OIDC federation | Over-scoped default token permissions (write instead of read), cloud role assumption from workflows |
| Internal SaaS reachable from runners | Jira, Confluence, Slack, internal APIs reachable via network position or leaked credentials from CI |
| Self-hosted runners | Persistent network foothold; job-to-host privilege escalation |
How the attack chain works (defender's view)
Based on the Wiz write-up, the chain follows a pattern every AppSec engineer should recognize:
- Injection point — the Autofix commit. Copilot Autofix generated a change (merged into the repo) that weakened the security posture of a GitHub Actions workflow — the classic shape being untrusted input (PR title, branch name, issue body, file contents) flowing into a shell context, or permissions being broadened to make a failing fix "work."
- Trigger condition. The vulnerable workflow ran on an event the Red Agent could influence (e.g.,
pull_request,issue_comment, or a trigger that executes on attacker-controlled input without requiring a write-access actor). - Code/command execution in CI. The agent achieved execution inside a workflow job — the runner is a compute environment with credentials attached.
- Credential harvesting. From the runner, the agent obtained tokens/secrets — either the
GITHUB_TOKENitself, environment-injected secrets, or credentials cached on the runner host. - Pivot to internal systems. Using harvested credentials and/or the runner's network position, the agent reached Snowflake's internal Jira and validated access to sensitive data.
- Blast radius assessment. The agent enumerated what else the stolen identity could reach — exactly what a human red teamer does after initial access.
Exploitation requirements
- Ability to open a PR or trigger a workflow event (often available to any external GitHub user on public repos, or any low-privilege internal user on private repos)
- A workflow that consumes event-controlled input in an
run:step, or grantsGITHUB_TOKENwrite permissions to untrusted-triggered jobs - Egress from the runner to internal or SaaS targets (self-hosted runners inside the corporate network are the worst case)
Exploitation status
- No CVE assigned; no vendor patch applies. This is a workflow-logic and permissions misconfiguration introduced by AI-generated code — the remediation is detection and pipeline hardening, not a package update.
- Confirmed in-the-wild demonstration by Wiz Red Agent against a production target (Snowflake's environment), with validated data access. Treat this technique class as actively exploitable today in any organization merging AI-suggested CI/CD changes without gatekeeping.
- Not in CISA KEV (no CVE exists), but GitHub Actions command injection and
pull_request_targetabuse are well-documented, actively exploited patterns — this incident proves AI tooling is now generating them.
Detection & Response
The highest-fidelity detections for this threat live in GitHub's audit log and on runner hosts. Below are rules I would deploy this week.
Sigma Rules
The following target (1) workflow file modifications by automated/AI actors, (2) privileged workflow approvals and self-hosted runner usage from forked PRs, and (3) command execution spawned by the GitHub Actions runner — the post-exploitation stage of this attack.
---
title: GitHub Actions Workflow Modified by Bot or AI Assistant
id: 3f9a1c7e-2b4d-4e8a-9c1f-5a6b7d8e9f01
status: experimental
description: Detects creation or modification of GitHub Actions workflow files by bot accounts or AI assistants (e.g., Copilot Autofix, dependabot, github-actions bot). These changes bypass normal human code review patterns and can introduce pipeline vulnerabilities.
references:
- https://www.wiz.io/blog/red-agent-snowflake-copilot-cicd-bug
- https://attack.mitre.org/techniques/T1195/
author: Security Arsenal
date: 2026/01/12
tags:
- attack.supply_chain_compromise
- attack.t1195.002
logsource:
product: github
service: audit
detection:
selection_action:
action:
- 'workflows.created_workflow'
- 'workflows.updated_workflow'
- 'protected_branch.update_required_status_checks'
- 'repo.actions_enabled'
selection_actor:
actor|contains:
- 'copilot'
- 'autofix'
- 'bot'
- 'dependabot'
condition: selection_action or (selection_actor and action|contains: 'workflow')
falsepositives:
- Legitimate Dependabot workflow updates (still warrants review of diff)
- Automation bots managed by platform engineering
level: high
---
title: GitHub Actions Workflow Job Approved or Queued on Self-Hosted Runner for External PR
id: 8b2e4d61-7c3a-4f5b-a2d8-1e9f0a3b5c72
status: experimental
description: Detects workflow jobs queued or approved for self-hosted runners, which grants PR-triggered code execution on hosts with internal network access. Key stage in the Wiz Red Agent pivot to internal Jira.
references:
- https://www.wiz.io/blog/red-agent-snowflake-copilot-cicd-bug
- https://attack.mitre.org/techniques/T1059/
author: Security Arsenal
date: 2026/01/12
tags:
- attack.execution
- attack.t1059
- attack.privilege_escalation
logsource:
product: github
service: audit
detection:
selection:
action:
- 'workflows.approve_workflow_job'
- 'workflows.prepare_workflow_job'
- 'workflows.queued_workflow_job'
condition: selection
falsepositives:
- Normal CI operations — baseline by repository and runner group, alert on deviations (new repo, external actor, non-standard runner label)
level: medium
---
title: GitHub Actions Runner Spawning Suspicious Child Processes
id: c47d2a19-5e6f-4a8b-b3c9-2d1e4f6a8b03
status: experimental
description: Detects the GitHub Actions runner process spawning shells, credential access, or network tooling indicative of pipeline compromise. On self-hosted runners this can precede lateral movement into internal systems such as Jira.
references:
- https://www.wiz.io/blog/red-agent-snowflake-copilot-cicd-bug
- https://attack.mitre.org/techniques/T1059/
author: Security Arsenal
date: 2026/01/12
tags:
- attack.execution
- attack.t1059.004
- attack.credential_access
logsource:
category: process_creation
product: windows
detection:
selection_parent:
ParentImage|endswith:
- '\Runner.Worker.exe'
- '\Runner.Listener.exe'
selection_suspicious:
CommandLine|contains:
- 'IEX'
- 'Invoke-Expression'
- 'DownloadString'
- 'Set-MpPreference'
- 'lsass'
- 'sekurlsa'
- '/token'
- 'vault'
- 'metadata.google.internal'
- '169.254.169.254'
condition: selection_parent and selection_suspicious
falsepositives:
- Build steps legitimately calling cloud metadata for OIDC — tune per-pipeline
level: high
KQL — Microsoft Sentinel / Defender
This query hunts GitHub audit log events (ingested via the GitHub connector into GitHubAuditLog_CL, or CommonSecurityLog via CEF) for risky workflow changes by automation accounts, then correlates with runner-side process execution from Defender for Endpoint on self-hosted runners.
// Hunt 1: Workflow file changes and privileged Actions events by non-human actors
let bots = dynamic(["copilot", "autofix", "dependabot", "github-actions", "bot"]);
GitHubAuditLog_CL
| where TimeGenerated > ago(14d)
| where Action_s has_any ("workflows.created_workflow", "workflows.updated_workflow",
"workflows.approve_workflow_job", "repo.actions_enabled",
"repo.actions_secret")
| extend ActorLower = tolower(Actor_s)
| where ActorLower has_any (bots)
or Action_s has "approve_workflow_job"
or Action_s has "actions_secret"
| project TimeGenerated, Actor_s, Action_s, Repo_s, Repository_s, OperationType_s, AdditionalFields_s
| order by TimeGenerated desc;
// Hunt 2: Self-hosted runner spawning credential or network tooling (Defender for Endpoint)
DeviceProcessEvents
| where TimeGenerated > ago(7d)
| where InitiatingProcessFileName in~ ("Runner.Worker.exe", "Runner.Listener.exe", "run.sh", "Runner.Worker")
or InitiatingProcessCommandLine has_any ("actions-runner", "_work")
| where FileName in~ ("powershell.exe", "pwsh.exe", "cmd.exe", "bash", "sh", "curl.exe", "curl", "wget", "whoami.exe", "id")
or ProcessCommandLine has_any ("169.254.169.254", "metadata", "token", "secret", "env", "IEX", "DownloadString")
| project TimeGenerated, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessCommandLine, ReportId
| order by TimeGenerated desc;
// Hunt 3: Runner hosts making unusual SaaS/API egress (pivot toward Jira-like internal targets)
DeviceNetworkEvents
| where TimeGenerated > ago(7d)
| where InitiatingProcessCommandLine has_any ("Runner.Worker", "actions-runner")
| where RemoteUrl has_any ("jira", "atlassian", "confluence", "slack.com", "vault", "okta")
| summarize Connections=count(), FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated)
by DeviceName, RemoteUrl, RemoteIP
| order by Connections asc; // rare destinations from CI runners are the tell
Velociraptor VQL
Deploy this artifact against self-hosted runner fleets to identify suspicious process execution and recently modified workflow checkouts — useful both for hunting and post-incident scoping.
-- Hunt GitHub Actions runner hosts for suspicious child processes and workflow modifications
LET procs = SELECT Pid, Ppid, Name, Exe, CommandLine, Username, CreateTime
FROM pslist()
WHERE CommandLine =~ '(?i)(runner\.worker|actions-runner|_work)'
OR Exe =~ '(?i)(actions-runner|Runner\.Worker)'
LET suspicious_children = SELECT Pid, Ppid, Name, Exe, CommandLine, Username, CreateTime
FROM pslist()
WHERE Ppid IN (SELECT Pid FROM pslist() WHERE Name =~ '(?i)Runner\.(Worker|Listener)|run\.sh|RunnerService')
AND CommandLine =~ '(?i)(169\.254\.169\.254|metadata|token|secret|curl|wget|iex|downloadstring|/etc/passwd|id$|whoami|env)'
LET workflow_files = SELECT FullPath, Mtime, Size
FROM glob(globs='C:\actions-runner\**\.github\workflows\*.yml',
accessor='file')
WHERE Mtime > now() - 604800
SELECT 'runner_process' AS Category, Pid, Ppid, Name, CommandLine, Username, CreateTime, '' AS FullPath, NULL AS Mtime FROM procs
UNION ALL
SELECT 'suspicious_child' AS Category, Pid, Ppid, Name, CommandLine, Username, CreateTime, '' AS FullPath, NULL AS Mtime FROM suspicious_children
UNION ALL
SELECT 'modified_workflow' AS Category, NULL, NULL, '', '', '', NULL, FullPath, Mtime FROM workflow_files
Remediation
Immediate actions (this week)
- Audit every workflow change authored or suggested by AI tooling. Pull the last 90 days of commits touching
.github/workflows/and filter by bot/autofix authors. Review each diff line-by-line for: broadenedpermissions:, addedpull_request_targettriggers, newrun:steps consuming${{ github.event.* }}context, and disabled branch protections. - Enforce explicit, minimal
GITHUB_TOKENpermissions. Default should bepermissions: read-allor a per-job least-privilege block at the workflow level — and set the org-level default to read-only under Settings → Actions → General → Workflow permissions. - Require approval for all outside collaborators' workflow runs, and never run forked PR code on self-hosted runners or with secrets. Gate
pull_request_targetbehind mandatory human review with a CODEOWNERS entry for.github/. - Treat AI-generated code as untrusted third-party code. Require human approval on all Autofix suggestions; consider disabling Autofix write-paths to CI/CD configuration entirely.
- Egress-control self-hosted runners. Deny runner subnets access to internal SaaS admin planes (Jira, Confluence, Okta, Vault) by default; allowlist only what builds genuinely need.
Audit and hardening script
Run this against your GitHub organization (requires gh CLI with read:org and actions:read scopes) to surface the exact patterns this incident weaponized:
#!/usr/bin/env bash
# github-actions-audit.sh — surface risky workflow patterns introduced by AI/bot commits
set -euo pipefail
ORG="${1:?Usage: $0 <github-org>}"
echo "=== [1] Repos with Copilot Autofix / code scanning autofix enabled ==="
gh api "orgs/$ORG/repos" --paginate -q '.[].full_name' | while read -r repo; do
autofix=$(gh api "repos/$repo" -q '.security_and_analysis.secret_scanning.status // "n/a"' 2>/dev/null || echo "unknown")
echo "$repo security_and_analysis=$autofix"
done
echo ""
echo "=== [2] Dangerous workflow patterns across org ==="
gh api "orgs/$ORG/repos" --paginate -q '.[].full_name' | while read -r repo; do
gh api "repos/$repo/contents/.github/workflows" -q '.[].download_url' 2>/dev/null | while read -r url; do
content=$(curl -fsSL "$url" 2>/dev/null || continue)
echo "$content" | grep -qE 'pull_request_target|issue_comment' && \
echo "[RISKY TRIGGER] $repo -> $url"
echo "$content" | grep -qE 'permissions:\s*$' && \
echo "$content" | grep -A6 'permissions:' | grep -qE 'contents:\s*write|actions:\s*write|id-token:\s*write' && \
echo "[WRITE TOKEN] $repo -> $url"
echo "$content" | grep -E '\$\{\{[^}]*github\.event\.(issue|comment|pull_request)\.(title|body|head\.ref)[^}]*\}\}' | grep -q 'run:' && \
echo "[SCRIPT INJECTION] $repo -> $url"
echo "$content" | grep -qE 'runs-on:.*self-hosted' && \
echo "[SELF-HOSTED] $repo -> $url"
done
done
echo ""
echo "=== [3] Workflow-file commits authored by bots/AI in the last 90 days ==="
gh api "orgs/$ORG/repos" --paginate -q '.[].full_name' | while read -r repo; do
gh api "repos/$repo/commits?path=.github/workflows&since=$(date -u -d '90 days ago' +%Y-%m-%dT%H:%M:%SZ)" \
-q '.[] | select(.author.login != null) | [.author.login, .commit.author.date, .sha[0:8], (.commit.message | split("\n")[0])] | @tsv' \
2>/dev/null | grep -iE 'copilot|autofix|\[bot\]|dependabot' | sed "s/^/$repo /"
done
echo ""
echo "=== [4] Missing CODEOWNERS protection on .github/ ==="
gh api "orgs/$ORG/repos" --paginate -q '.[].full_name' | while read -r repo; do
if ! gh api "repos/$repo/contents/CODEOWNERS" >/dev/null 2>&1 && \
! gh api "repos/$repo/contents/.github/CODEOWNERS" >/dev/null 2>&1; then
echo "[NO CODEOWNERS] $repo"
fi
done
echo ""
echo "=== [5] Org default workflow permissions (want: read) ==="
gh api "orgs/$ORG/actions/permissions/workflow" -q '{default: .default_workflow_permissions, can_approve: .can_approve_pull_request_reviews}'
Configuration hardening checklist
| Control | Setting | Where |
|---|---|---|
| Default token scope | default_workflow_permissions: read | Org → Actions → General |
| Fork PR approvals | Require approval for all outside collaborators | Org → Actions → General |
| Autofix review | Mandatory human review on all Copilot Autofix PRs; block Autofix on workflow paths via branch rulesets | Repo → Rules → Rulesets |
| CODEOWNERS | /.github/ @platform-security-team | Repo root or .github/ |
| Self-hosted runners | Ephemeral runners only; no org-level self-hosted runner access for public repos; network segmentation from internal SaaS | Runner groups + firewall policy |
| Secrets | OIDC federation to cloud instead of long-lived secrets; environment protection rules with required reviewers | Repo → Environments |
| Script injection | Use intermediate env vars for ${{ github.event.* }} values instead of inline interpolation | Workflow YAML |
Longer-term program changes
- Adopt continuous CI/CD red teaming. The uncomfortable takeaway from Wiz's disclosure: an autonomous agent did in hours what most organizations test annually. If you aren't continuously probing your own pipelines, someone else's agent will. Include GitHub Actions, GitLab CI, and Azure DevOps in your attack surface management scope.
- Establish an AI-code provenance policy. Log and tag all commits authored or co-authored by AI assistants. Route them through enhanced review and targeted SAST/DAST before merge.
- Monitor for post-exploitation pivoting. The Jira access in this incident was the impact, not the entry point. Alert on CI/CD identities and runner hosts touching systems outside their build-time baseline — that's where you catch this class even when the workflow flaw itself evades review.
- Reference vendor guidance: GitHub — Security hardening for GitHub Actions, Wiz disclosure, and OpenSSF guidance on AI-assisted code review.
This incident is a preview, not an anomaly. AI will write more of your pipeline code, and autonomous agents — yours and adversaries' — will continuously test it. The organizations that survive this shift are the ones that instrument CI/CD like the production attack surface it is.
Related Resources
Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub
Is your security operations ready?
Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.