
Wiz Red Agent Finds Its Way Into Snowflake’s Internal Jira Through a Flaw in a GitHub Copilot–Assisted PR
Wiz's autonomous "Red Agent" discovered a GitHub Actions script-injection vulnerability in snowflakedb/snowflake-connector-net's jira_issue.yml workflow, introduced when a PR (co-authored by GitHub Copilot) replaced a safe env:/jq pattern with direct interpolation of the attacker-controlled issue title. GitHub Advanced Security scanned the same PR and workflow but failed to flag the injection; Red Agent autonomously crafted and self-corrected a payload after a bash syntax error, exfiltrated Jira OAuth credentials via an out-of-band callback, and used them to access Snowflake's internal Jira (engineering, security, and bug-bounty projects) — all without human intervention. Snowflake patched and rotated credentials the same day the flaw was reported via HackerOne.
What it is
A GitHub Actions script-injection flaw in snowflakedb/snowflake-connector-net's jira_issue.yml workflow, live from June 18–23, 2026 (introduced by PR #1218, commit 4a1b8ce; fixed by PR #1402, commit 1dc7766). The summary covers the discovery narrative; what matters for an engineer is the exact defective pattern, the reason the "security gate" didn't hold, and the payload mechanics — all reproducible.
How it works
The workflow triggered on issues: opened, so any unauthenticated GitHub user could fire it, and it interpolated the issue title straight into a run: block:
run: |
TITLE=$(echo '${{ github.event.issue.title }}' | sed 's/"/\\"/g' | sed "s/'/\\\'/g")The sed escaping runs after GitHub's template expansion, so a single quote in the title breaks out of echo '...'. Command execution follows.
The if: gate looked protective but compared against github.event.pull_request — which is always null on issues events. The check reduced to (null != 'whitesource-for-github-com[bot]'), always true, so every user passed. This is the detail worth internalizing: an actor-allowlist gate keyed on a field the triggering event never populates is no gate at all.
The prior safe form — an env: variable plus jq --arg parsing — was removed in the same PR and replaced by direct ${{ ... }} interpolation.
What to do
- Audit
run:blocks for direct${{ github.event.* }}interpolation of attacker-controlled fields (issue/PR titles, bodies, branch names). Pass untrusted input throughenv:and reference it as a shell variable, or parse withjq --arg— the pattern Snowflake restored. - Verify that any
if:actor/author guard references a field the triggering event actually populates;github.event.pull_requestis null onissuesevents. - Treat AI-authored/AI-reviewed PRs under the same static analysis as human code — here GitHub Advanced Security explicitly extracted the vulnerable workflow and did not flag it, and Copilot as co-author marked the change all-clear.
- Use short-lived credentials: the exposure window was five days, and an autonomous agent found and exploited it within that window.
Caveats
GitHub Advanced Security scanned the final PR revision including this workflow and missed the injection — do not treat its pass as coverage for this class. The page notes it is "unclear whether the code-change was AI-assisted"; Copilot's confirmed role was reviewing the merged PR and a separate Autofix on jira_close.yml, not authoring the injection.
Organisations named here
- Red Agent
- Wiz Research
Technologies named here
- Wiz Red Agent
- snowflakedb/snowflake-connector-net
- GitHub Advanced Security
- snowflakecomputing.atlassian.net
- GitHub Copilot / Copilot Autofix
- HackerOne
- GitHub Actions
- GitHub Copilot
- Jira
- Wiz
Techniques named here
- GitHub Actions script/command injection
- Security gate bypass via null condition
- Out-of-band data exfiltration
- Autonomous payload adjustment after syntax error
Related in DevSecOps
JFrog: The Governance Gap Between Your Policy and Your Pipeline

Dev Machine Guard Now Supports Windows - StepSecurity

Socket: TanStack npm Packages Compromised
