A Wiz researcher recently disclosed that an AI-driven analysis agent identified a critical security flaw in Snowflake's GitHub repository — specifically within its GitHub Actions CI/CD workflow configuration — that GitHub Advanced Security's own scanning had missed entirely. The finding, reported by Infosecurity Magazine, is not just a win for one vendor's tooling. It is a loud, practical warning about the structural blind spots in how most organizations secure their software supply chain.
If a company of Snowflake's engineering maturity — one that has already weathered one of the most consequential SaaS breach campaigns in recent memory — can ship a critical workflow flaw past native GitHub scanning, your repositories almost certainly have similar exposure. This post breaks down what this class of vulnerability looks like, why conventional scanners miss it, and how to hunt for and remediate it across your own organization.
Why This Matters Right Now
GitHub Actions has become the control plane for modern software delivery. A compromised workflow is not a code bug — it is a pipeline for attackers to:
- Steal cloud credentials and secrets exposed to build jobs (AWS/Azure/GCP keys, OIDC tokens, signing certificates)
- Poison build artifacts that ship directly to customers
- Pivot into production environments via self-hosted runners with network adjacency to internal systems
- Exfiltrate source code and access tokens with broad repository scopes
The threat actor community has fully internalized this. The 2024–2025 wave of supply-chain intrusions — including the tj-actions/changed-files compromise and the broader campaign targeting CI secrets — demonstrated that workflow files are now a first-class attack surface, actively hunted by nation-state and criminal operators alike. A critical flaw sitting undetected in a high-profile repo like Snowflake's is precisely the kind of weakness that gets weaponized within days of public discussion.
Technical Analysis: The Vulnerability Class
While full technical specifics of the Snowflake finding remain limited in public reporting, the disclosure describes a critical flaw in a GitHub Actions workflow that evaded pattern-based scanning. In my experience auditing CI/CD environments, the flaws that consistently slip past native scanners — and that an AI reasoning agent is well-suited to catch — fall into a small number of well-understood categories:
1. Script Injection via Untrusted Context Interpolation
The most dangerous and most commonly missed flaw. When a workflow interpolates untrusted GitHub context data (PR titles, branch names, commit messages, issue bodies) directly into a run: step, an attacker who can open a pull request or issue can inject arbitrary shell commands:
# VULNERABLE PATTERN — do not use in production
- name: Check PR title
run: echo "Processing ${{ github.event.pull_request.title }}"
The safe pattern routes untrusted input through an environment variable, which prevents shell interpretation:
- name: Check PR title
env:
PR_TITLE: ${{ github.event.pull_request.title }}
run: echo "Processing $PR_TITLE"
2. pull_request_target Abuse
Workflows triggered by pull_request_target run in the context of the target repository — with access to secrets and a read/write GITHUB_TOKEN — while potentially checking out and executing attacker-controlled code from a fork. Scanners frequently flag the trigger itself but miss the data-flow combination of pull_request_target plus a checkout of github.head_ref followed by a build/test step that executes forked code. Reasoning over that multi-step chain is exactly where AI agents outperform signature matching.
3. Over-Permissive GITHUB_TOKEN and Missing permissions: Blocks
Workflows without an explicit least-privilege permissions: block may inherit read/write token scopes, enabling a compromised step to push code, modify releases, or alter branch protections.
4. OIDC and Secret Exposure
Workflows granting id-token: write to jobs triggered by untrusted events allow attackers to mint cloud OIDC tokens. Combined with script injection, this is a direct path to cloud account compromise.
Why GitHub Advanced Security Missed It
This is the core defensive lesson. GitHub Advanced Security (CodeQL, secret scanning, dependency review) is primarily pattern and dataflow analysis over code, not security-logic reasoning over workflow semantics. CodeQL's Actions support is limited compared to its coverage of application languages, and static rules struggle with the combinatorial context of triggers, permissions, job dependencies, and shell interpolation. The Wiz agent reportedly succeeded by reasoning about the workflow the way an attacker would — chaining context, permissions, and reachability. Defenders should treat this as confirmation that no single scanner is sufficient for CI/CD posture.
Exploitation Status
No public proof-of-concept or in-the-wild exploitation of the specific Snowflake flaw has been reported, and no CVE identifier has been published as of this writing. The flaw was responsibly disclosed and Snowflake was notified. However, the vulnerability class — GitHub Actions injection and token abuse — is actively exploited in the wild and has been central to multiple 2025 supply-chain incidents. Treat any comparable finding in your own repos as pre-exploitation reconnaissance terrain.
Detection & Response
The detections below target the observable behaviors of CI/CD workflow compromise: malicious workflow modifications, anomalous runner process execution, and secret access patterns. They assume GitHub audit log streaming into Sentinel and telemetry from self-hosted runners.
Sigma Rules
---
title: GitHub Actions Workflow File Modified with Dangerous Trigger or Injection Pattern
id: 3f8a1c42-7b9e-4d51-a6c2-9e1f5b8d3a07
status: experimental
description: Detects commits or file changes introducing pull_request_target triggers or untrusted context interpolation into GitHub Actions workflow files, a pattern associated with CI/CD script injection and supply-chain compromise as seen in the Snowflake workflow flaw disclosed by Wiz.
references:
- https://www.infosecurity-magazine.com/news/wiz-ai-agent-finds-snowflake/
- https://attack.mitre.org/techniques/T1195/
- https://attack.mitre.org/techniques/T1078/
author: Security Arsenal
date: 2026/01/15
tags:
- attack.initial_access
- attack.t1195.002
- attack.t1078
logsource:
product: github
service: audit
detection:
selection_path:
name|contains: '.github/workflows'
selection_content:
- 'pull_request_target'
- '${{ github.event.issue.'
- '${{ github.event.pull_request.title'
- '${{ github.event.pull_request.body'
- '${{ github.head_ref'
- '${{ github.event.comment.body'
condition: selection_path and selection_content
falsepositives:
- Legitimate workflow updates by developers — validate against change tickets and require peer review for workflow changes
level: high
---
title: Suspicious Child Process Spawned by GitHub Actions Self-Hosted Runner
id: 8c2e5d19-4a6f-4b83-91d4-2c7a9e0f6b35
status: experimental
description: Detects self-hosted GitHub Actions runner worker processes spawning shells, download cradles, or cloud metadata clients, consistent with post-exploitation of a compromised workflow (e.g., after script injection in a vulnerable workflow file).
references:
- https://www.infosecurity-magazine.com/news/wiz-ai-agent-finds-snowflake/
- https://attack.mitre.org/techniques/T1059/
- https://attack.mitre.org/techniques/T1552.005/
author: Security Arsenal
date: 2026/01/15
tags:
- attack.execution
- attack.t1059.004
- attack.credential_access
- attack.t1552.005
logsource:
category: process_creation
product: windows
detection:
selection_parent:
ParentImage|endswith:
- '\Runner.Worker.exe'
- '\Runner.Listener.exe'
selection_child:
Image|endswith:
- '\powershell.exe'
- '\pwsh.exe'
- '\cmd.exe'
- '\curl.exe'
- '\certutil.exe'
- '\bitsadmin.exe'
selection_cmd:
CommandLine|contains:
- 'Invoke-WebRequest'
- 'iwr '
- 'iex'
- 'DownloadString'
- '169.254.169.254'
- '-enc '
- 'FromBase64String'
condition: selection_parent and selection_child and selection_cmd
falsepositives:
- Build steps legitimately invoking package downloads — baseline per repository and alert on deviation
level: high
---
title: Linux Runner Executing Cloud Metadata or Secret Access Commands
id: 5d1b7f03-9c48-4e62-b7a1-6f3d8a2c4e90
status: experimental
description: Detects Linux-based GitHub Actions runner processes accessing cloud instance metadata endpoints or dumping environment variables, indicating CI secret harvesting following workflow injection.
references:
- https://www.infosecurity-magazine.com/news/wiz-ai-agent-finds-snowflake/
- https://attack.mitre.org/techniques/T1552.005/
- https://attack.mitre.org/techniques/T1528/
author: Security Arsenal
date: 2026/01/15
tags:
- attack.credential_access
- attack.t1552.005
- attack.t1528
logsource:
category: process_creation
product: linux
detection:
selection_cmd:
CommandLine|contains:
- '169.254.169.254'
- 'metadata.google.internal'
- 'printenv'
- '/proc/self/environ'
- 'env |'
- 'AWS_SESSION_TOKEN'
- 'ACTIONS_ID_TOKEN_REQUEST'
filter_known_benign:
CommandLine|contains:
- 'az login --identity'
- 'aws sts get-caller-identity'
condition: selection_cmd and not filter_known_benign
falsepositives:
- Legitimate OIDC federation steps in hardened workflows — these should be enumerated and allowlisted explicitly
level: high
KQL — Microsoft Sentinel (GitHub Audit Log + Endpoint)
The first query hunts workflow file modifications and permission escalation events in the GitHub audit stream; the second hunts anomalous process execution on self-hosted runners ingested via Defender for Endpoint.
// Hunt 1: Workflow file changes introducing dangerous triggers or injection sinks
// Requires GitHub audit log streaming to Sentinel (GitHubAuditLog / CommonSecurityLog via connector)
GitHubAuditLog
| where TimeGenerated > ago(14d)
| where Action in ("workflows.created_workflow", "workflows.updated_workflow",
"repo.actions_secret_accessed", "pull_request_target.enabled")
or (Action == "git.push" and FilePaths has ".github/workflows")
| extend DangerPattern = iff(FileContent has_any ("pull_request_target",
"github.event.pull_request.title", "github.head_ref",
"github.event.issue.title", "github.event.comment.body"), true, false)
| where DangerPattern == true or Action startswith "workflows."
| project TimeGenerated, Actor, Repository, Action, FilePaths, DangerPattern, IPAddress
| sort by TimeGenerated desc;
// Hunt 2: Suspicious child processes under self-hosted runner workers (MDE telemetry)
DeviceProcessEvents
| where TimeGenerated > ago(7d)
| where InitiatingProcessFileName in~ ("Runner.Worker.exe", "Runner.Listener.exe", "run.sh", "Runner.Worker")
| where FileName in~ ("powershell.exe", "pwsh.exe", "cmd.exe", "curl.exe", "wget",
"bash", "sh", "certutil.exe", "python", "python3")
| where ProcessCommandLine has_any ("169.254.169.254", "metadata.google.internal",
"DownloadString", "FromBase64String", "printenv", "/proc/self/environ",
"ACTIONS_ID_TOKEN_REQUEST", "AWS_SESSION_TOKEN", "-enc ")
| project TimeGenerated, DeviceName, AccountName, FileName, ProcessCommandLine,
InitiatingProcessCommandLine, SHA256
| sort by TimeGenerated desc;
Velociraptor VQL — Runner Host Forensics
Deploy this artifact across self-hosted runner pools to identify live secret-harvesting behavior and recently modified workflow checkouts.
-- Hunt self-hosted GitHub Actions runner hosts for post-injection behavior
-- Targets: runner-spawned shells, metadata access, env harvesting, recent workflow file edits
LET procs = SELECT Pid, Ppid, Name, CommandLine, Exe, Username, CreateTime
FROM pslist()
WHERE CommandLine =~ '169\\.254\\.169\\.254|metadata\\.google\\.internal|printenv|/proc/.*/environ|ACTIONS_ID_TOKEN_REQUEST|AWS_SESSION_TOKEN|DownloadString|FromBase64String'
OR (Name =~ '(?i)runner\\.worker|run\\.sh' AND CommandLine =~ '(?i)bash|sh -c|powershell|pwsh')
LET workflows = SELECT FullPath, Size, Mtime, Btime
FROM glob(globs='**/actions-runner/_work/*/.github/workflows/*.y*ml')
WHERE Mtime > now() - 1209600 -- modified in last 14 days
SELECT * FROM procs
UNION ALL
SELECT NULL AS Pid, NULL AS Ppid, 'WORKFLOW_FILE' AS Name, FullPath AS CommandLine,
NULL AS Exe, NULL AS Username, Mtime AS CreateTime
FROM workflows
Remediation & Audit Script
The following Bash script uses the GitHub CLI to enumerate every repository in your organization and flag the exact dangerous patterns implicated in this vulnerability class. Run it weekly as a scheduled task or CI job.
#!/bin/bash
# audit-gha-workflows.sh — Scan all org repos for dangerous GitHub Actions patterns
# Requires: gh CLI authenticated with repo + workflow scope, jq installed
set -euo pipefail
ORG="YOUR_ORG_NAME"
REPORT="gha_audit_$(date +%Y%m%d).csv"
echo "repo,workflow,issue" > "$REPORT"
for repo in $(gh repo list "$ORG" --limit 1000 --json nameWithOwner -q '.[].nameWithOwner'); do
# List workflow files in default branch
workflows=$(gh api "repos/$repo/contents/.github/workflows" --jq '.[].path' 2>/dev/null || true)
[ -z "$workflows" ] && continue
for wf in $workflows; do
content=$(gh api "repos/$repo/contents/$wf" --jq '.content' | base64 -d)
echo "$content" | grep -q "pull_request_target" && \
echo "$repo,$wf,USES_pull_request_target" >> "$REPORT"
echo "$content" | grep -qE '\$\{\{[[:space:]]*github\.(event\.(pull_request\.(title|body)|issue\.(title|body)|comment\.body)|head_ref)' && \
echo "$repo,$wf,UNTRUSTED_CONTEXT_IN_RUN_STEP (injection risk)" >> "$REPORT"
echo "$content" | grep -q "pull_request_target" && \
echo "$content" | grep -qE 'ref:[[:space:]]*\$\{\{.*head' && \
echo "$repo,$wf,CRITICAL_pull_request_target_WITH_FORK_CHECKOUT" >> "$REPORT"
grep -q "permissions:" <<< "$content" || \
echo "$repo,$wf,NO_EXPLICIT_PERMISSIONS_BLOCK" >> "$REPORT"
echo "$content" | grep -q "id-token: write" && \
echo "$content" | grep -qE 'pull_request' && \
echo "$repo,$wf,OIDC_TOKEN_ON_PR_TRIGGER" >> "$REPORT"
done
done
echo "[+] Audit complete. Findings in $REPORT"
awk -F, 'NR>1 {print $3}' "$REPORT" | sort | uniq -c | sort -rn
Remediation
-
Audit every workflow in every repo this week. Run the script above (or an equivalent using your SCM's API). Prioritize any finding of
pull_request_targetcombined with a fork checkout — that is the highest-severity pattern and the one most analogous to a critical flaw. -
Eliminate untrusted context interpolation in
run:steps. Replace direct${{ github.event.* }}interpolation of attacker-controllable fields withenv:variable indirection. Reference: GitHub Security Hardening for Actions. -
Enforce least-privilege tokens. Add an explicit
permissions:block to every workflow, defaulting tocontents: read. Set the organization default forGITHUB_TOKENto read-only in GitHub org settings, and require approval for all outside-collaborator and fork PR workflow runs. -
Gate workflow changes like production code. Require CODEOWNERS review for anything under
.github/workflows/, and route workflow modification events from the GitHub audit log to your SIEM (the KQL above assumes this integration exists — if it doesn't, build it today). -
Diversify your scanning stack. The central lesson of the Snowflake finding: GitHub Advanced Security alone did not catch it. Layer complementary tools — static workflow linters (e.g., zizmor, actionlint with security rules), AI-assisted review, and manual red-team review of critical pipelines. Single-scanner confidence is a documented failure mode.
-
Harden self-hosted runners. Ephemeral, single-job runners only. No persistent runners with cached credentials. Isolate runner networks from production segments, and block cloud metadata endpoints where OIDC is not in use.
-
Rotate secrets on any confirmed injection exposure. If your audit finds an exploitable pattern that was reachable from forked PRs, assume secrets available to that job may have been exposed and rotate them.
There is no CVE or vendor patch here — the remediation is configuration, process, and defense-in-depth. That is precisely why these flaws persist past scanners, and why they reward attackers who go looking.
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.