Originally published at getunblocked.com on August 17, 2026.
On June 18, 2026, a routine-looking pull request merged into snowflake-connector-net, Snowflake's public .NET driver repository. PR #1218, "SNOW-2069227: Update jira workflows," reworked the repository's Jira automation, and it carried a co-author trailer that would later make headlines: "Copilot Autofix powered by AI." Somewhere in that refactor, the existing sanitized-input pattern in the jira_issue.yml GitHub Actions workflow disappeared, replaced by direct string interpolation in a run: block. For five days, any GitHub user with a crafted issue title could execute commands inside Snowflake's CI.
On June 23, Wiz Research's autonomous "Red Agent" found the flaw while scanning Snowflake's GitHub organization, built a working exploit, and pulled a Jira API token through an out-of-band callback. Wiz reported it through Snowflake's HackerOne program that day. Snowflake patched it the same day, rotated the token on June 24, and its investigation found no evidence of unauthorized access. The full writeup went public on August 17.
In brief: The Copilot Autofix Snowflake incident isn't a story about reckless AI. A refactor removed a sanitization pattern nobody remembered the reason for, an AI reviewer and a human reviewer both approved it, and an AI security agent exploited the gap five days later. The failure was missing context, not too much automation.
What actually happened?
The refactor reworked how the repository's workflows talked to Jira, and along the way jira_issue.yml lost its safe input handling. The old workflow passed the issue title through an env: variable and built its JSON payload with jq --arg, so untrusted text never touched the shell parser. The new version interpolated ${{ github.event.issue.title }} straight into a run: block. One single quote in an issue title and you're out of the echo string, running arbitrary commands on the runner.
A guard condition made it worse by looking effective. The workflow checked github.event.pull_request.user.login, a field that's always null on issue events, so the check blocked nobody. When Wiz's Red Agent scanned the repo on June 23, it spotted the pattern, hit a shell syntax error on its first attempt, analyzed the failure, adjusted its payload, and exfiltrated the Jira token for qa@snowflake.net. That token had read access to Snowflake's engineering, security compliance, and bug bounty projects. Wiz deleted everything it accessed, and Snowflake's audit review found no other third party had touched the endpoint during the five-day window.
What was Copilot Autofix's actual role?
Here's where early headlines got ahead of the facts. The commit carries a Co-authored-by trailer for "Copilot Autofix powered by AI," and initial coverage read that as the AI writing the vulnerable change. Wiz has since updated its post to clarify: Copilot Autofix checked the merged PR and code change and identified it as all-clear without noticing the critical vulnerabilities. Whether the deletion itself was AI-assisted is unclear; The Hacker News reports the bot's direct modification was to jira_close.yml, while a Snowflake engineer authored the jira_issue.yml change.
The correction sharpens the lesson rather than softening it. GitHub's own docs are candid that Autofix "may suggest fixes that fail to remediate the underlying vulnerability or introduce new vulnerabilities," and that every suggestion requires explicit developer review. In the Copilot Autofix Snowflake timeline, the AI in the loop wasn't a rogue author. It was one of the review tools in the pipeline, and it blessed a change it had no reason to distrust.
Why did review miss it?
Because everyone reviewing it, human and machine, was judging the diff on its face. The env: plus jq indirection is exactly the mitigation GitHub's security hardening guide prescribes for untrusted input, which strongly suggests it was there on purpose. But nothing in the diff said so. No comment, no linked decision, no trace of whoever added it or why. That's Chesterton's fence, agent edition: the fence got removed because nothing in anyone's context explained what it was holding back.
To a reviewer who only sees the diff, deleting that indirection reads as simplification: a cleaner script with fewer moving parts. The stated goal of the PR was modernization, and against that goal the change looks like progress. Commenters on Hacker News were honest about it: "I probably would have made the same mistake." The change was context-blind, and so was the review of it. Agents can't see what isn't in their context, rules files rot, and models confronted with a gap will fill it with something plausible. Plausible is what got merged.
What would context-aware review have seen?
The history the diff couldn't show. Somewhere in the repository's past sits the change that introduced the env:/jq pattern, and, if it was deliberate, whatever hardening pass or review discussion put it there: the moment someone decided issue titles should never touch a run: block directly. A reviewer with access to that history could have seen the deletion not as a simplification but as a guardrail coming down, and asked why it was safe to remove.
This is the case for context-aware code review, and it's what we build at Unblocked: an institutional-memory layer for PR review that surfaces the decisions behind the code, pulling decision-grade context from PRs, docs, and team chat into the moment a change is judged. One of our customers put it plainly:
"LLMs are only as good as their context, and code alone gives them a narrow view — the codebase is always behind where the team wants to go. When I plugged Unblocked into our context-gathering and PR review steps, it brought in the Slack conversations where real architectural decisions get made. We went from three rounds of PR review to one before the code was production-ready." — Pablo Vallejo, Engineering Manager, Clio
Review that remembers why is review that can catch a deleted fence.
What should teams change this week?
The most transferable Copilot Autofix Snowflake lessons are mechanical. Run a workflow auditor like zizmor in CI; its template-injection audit flags exactly the ${{ }}-in-run: pattern that burned Snowflake. Enforce GitHub's intermediate-environment-variable rule for anything derived from github.event, and test your guard conditions against the events they actually fire on, since a check that references a nonexistent field fails open.
Then fix the context layer, because linters only catch known patterns. Treat AI-co-authored changes to security-relevant files, workflows, auth code, and input handling as a signal to review harder, not a reason to skim. Agents confidently ship changes their training and context can't justify, whether that's calling deprecated APIs or deleting sanitization, and the burden of catching that lands on review. Finally, when you remove code that looks like defensive indirection, make the PR say why it's safe to remove. And wire your reviewers, human and AI, to a source of truth that includes decision history, so "why does this exist?" gets answered before the merge button, not after the disclosure.
FAQ
Did Copilot Autofix write the vulnerable code?
It's unclear, and Wiz says so explicitly in its updated post. What's documented: the merged commit lists Copilot Autofix as a co-author, the bot's direct modification appears to be jira_close.yml, a Snowflake engineer authored the jira_issue.yml change, and Autofix reviewed the result and raised no alarm. Attribution aside, the operative fact doesn't change: both the AI review path and the human review path looked at the removal of a working guardrail and approved it.
Was Snowflake customer data exposed?
There's no evidence of it. The token at the center of the Copilot Autofix Snowflake exposure granted read access to internal Jira projects, not the Snowflake data platform. Snowflake patched the same day it was notified, rotated the token the next day, and stated its investigation "found no evidence of unauthorized access." Audit review showed Wiz was the only third party on that endpoint during the exposure window, per The Register.
Would a static analysis tool have caught this?
Almost certainly. Tools like zizmor and actionlint detect template expansion of untrusted context values in run: blocks, and Hacker News commenters made the same point: writing GitHub Actions without static analysis is asking for exactly this. Notably, the vulnerable pattern is the textbook example in GitHub's own hardening guide, so the detection rules are mature. But linters wouldn't have explained why the old pattern existed, and they won't flag the next guardrail that doesn't match a known signature. Pattern-matching catches the known footguns; context catches the fences.
The uncomfortable symmetry
An AI waved this bug into production and an AI dug it back out, and the difference between them wasn't capability but what each one knew. Red Agent arrived with an adversarial mission, deep knowledge of injection patterns, and the persistence to iterate when its first exploit threw a syntax error. Autofix reviewed a diff with no knowledge of why the old code was shaped the way it was, no memory of the review that shaped it, and no reason to ask. Same class of model, opposite outcomes, entirely determined by context.
Snowflake, for its part, handled the incident the way you'd want: same-day patch, next-day token rotation, cooperative disclosure, and a public commitment to share the lessons. None of that is a reason to pull agents out of your pipeline. The lesson of the Copilot Autofix Snowflake incident is that every reviewer you add, silicon or human, is only as good as the history you give it. Give your review process the memory your repo doesn't have.
Top comments (0)