Two malicious versions of axios hit npm on March 31, 2026. The maintainers pulled them after three hours. By then, OpenAI's macOS app-signing pipeline had already downloaded and executed one of them.
The attack path was straightforward. An attacker compromised the machine of axios's lead maintainer through social engineering, bypassed 2FA, and published two poisoned versions: axios@1.14.1 and axios@0.30.4. Both packages declared a phantom dependency called plain-crypto-js@4.2.1 that had never existed on npm before. The payload inside was a multi-platform RAT dropper designed to establish persistence and exfiltrate environment variables, SSH keys, and credentials.
How OpenAI Got Caught
OpenAI's GitHub Actions workflow for macOS code signing referenced axios using a floating version tag, the standard semver range that most projects ship without thinking twice. When the CI pipeline triggered during the three-hour compromise window, it resolved to the poisoned axios@1.14.1 and executed it as part of the build.
The signing pipeline runs with elevated privileges by definition. It needs access to code-signing certificates, entitlements, and notarization tokens. Few contexts are worse for running unvetted code.
Attack timeline
| Step | Action | Result |
|---|---|---|
| 1 | Social engineering + RAT on maintainer PC | npm account access |
| 2 | Bypassed 2FA, published axios@1.14.1 | Malicious package on npm |
| 3 | OpenAI GH Actions pulled floating tag | Poisoned dependency in build |
| 4 | Build step executed RAT dropper | Signing pipeline compromised |
| 5 | Certificate exposure | All macOS apps need re-signing |
OpenAI says no user data was accessed. Word choice matters here. With a RAT dropper running inside the signing pipeline, "no data was accessed" and "we detected no access" describe different things. Forensic details have not been published.
The Cleanup
OpenAI is revoking all macOS code-signing certificates and rebuilding four products from scratch: ChatGPT Desktop, Codex, Atlas, and Codex CLI. Every macOS user will need to update. The hard deadline is May 8, 2026, after which older app versions stop working.
This is the right call. Rotating certificates is expensive and disruptive, but the alternative is trusting that a RAT dropper in your signing environment touched nothing. Wrong place to extend trust.
Chart data
| Label | Value |
|---|---|
| Published to npm (00:21) | 0 min |
| Community reports (01:00) | 39 min |
| npm contacted (01:38) | 77 min |
| Packages pulled (03:15) | 174 min |
The Real Lesson
The axios compromise hit many more projects than OpenAI. The OpenAI case is the most instructive because it shows what happens when a floating dependency meets a privileged CI environment.
Pinning by commit hash instead of semver tag would have prevented this entirely. So would a lockfile check that fails on unexpected dependency additions. So would running signing in an isolated environment without network access to npm. None of these are exotic practices. They are just not the defaults.
Full disclosure: I run PromptScript. The same problem of unpinned remote sources gets a different answer there. promptscript.lock records exact resolved commits for every remote import, so reproducibility covers the whole project, not just one package. I will cover it in a separate article.
Three hours, one floating tag, certificate rotation across an entire product line. The supply chain is exactly as strong as the laziest package.json entry in the build.
Sources: OpenAI