The uncomfortable part of the GitHub Actions compromise reported on October 9 isn’t the scale. It’s where the code ran. Attackers took over two high-profile maintainer accounts — including Takashi Kitao, author of the 18,400-star Pyxel engine — and pushed malicious workflows into more than 340 repositories. Those workflows didn’t drop a binary on your laptop. They executed inside CI, under the identity you deliberately granted, with access to the secrets you deliberately handed over. Endpoint AV sees nothing because nothing bad touched an endpoint.
The mechanism is boring, which is exactly why it works. A new file lands in .github/workflows/ — or a step gets appended to an existing one — and on the next run it reads ${{ secrets.* }}, scrapes the environment, and POSTs it to an attacker-controlled host. GitHub secrets, CI tokens, cloud provider keys, package registry credentials: anything exposed to that job’s environment is in scope. If a maintainer account can commit to a repo, it can rewrite the thing that runs on push. That’s the whole trick. No platform zero-day, no CVE — just a trusted account doing trusted things with someone else’s hands on the keyboard.
So the question that actually decides your morning isn’t “are we on the list of 340.” It’s “did a job run with our secrets between the compromise and the cleanup.” If you forked an affected project, pulled it as a Git submodule, or — worse — reference a third-party action by a mutable tag like @v2 or @main, you inherited whatever that ref pointed at when your runner fetched it. Pinning to tags is the quiet default that bites you here.
Start local. Grep your workflow files for the shapes this attack leaves behind — secrets being piped into network calls, base64 blobs, environment dumps:
Grep tells you what the workflow says. The audit log tells you what it did. For org-owned repos, pull workflow-run history and the secret-related events around the compromise window so you know whether a tainted job actually executed:
Turn on GitHub secret scanning with push protection if it isn’t already — it catches the leaked-credential half of the problem, not the exfiltration half, but it’s free and it’s on the right side of the fence. Pair it with the audit-log review above; neither is sufficient alone.
Now the part people flinch at. If a job with access to a secret ran a workflow you can’t fully vouch for during that window, treat the secret as burned and rotate it. All of it — not the ones that “look” exposed. Cloud keys, registry tokens, the lot. Exfiltrated credentials don’t announce themselves, and “we think it was fine” is not an incident finding. While you’re in there, drop default GITHUB_TOKEN permissions to read-only (permissions: contents: read) and grant up from there per job, require pinned commit SHAs for third-party actions, and enable repository rulesets so a single compromised account can’t silently rewrite .github/workflows/ again.
Do the grep and the audit-log pull today — it’s an hour and it tells you whether you have an incident. Rotate anything a suspect job could reach this week. The pinning and permissions cleanup is next-cycle work, but skip it and you’re just waiting for the next maintainer to get phished.
The lesson isn’t “GitHub is unsafe.” It’s that “trusted” in a CI pipeline means “runs with your keys,” and trust you granted to a human transfers cleanly to whoever steals that human’s session. Scanners guard the door. This walked in through the one you propped open.
