Adventures in Nodeland logo

Adventures in Nodeland

Archives
May 2, 2026

Why “Trusted Publishing” Can’t Save Us from Social Engineering

Unmasking the risky illusion of npm's "trusted publishing" amidst recent cyber attacks.

Hey Everyone!

I want to talk about something that’s been bothering me since the Axios compromise. This issue goes beyond just one package. First, a quick definition: In the npm ecosystem, “trusted publishing” means using tools (like Sigstore and OIDC) to confirm that a package was published by a verified identity and built using a verified process, typically through a secure continuous integration (CI) pipeline. The idea is to give consumers cryptographic proof of who published the package and with what workflow. It’s about the main promise of npm “trusted publishing” and why, given the attacks we’re seeing now, it’s a risky illusion.

Here’s the short version: Trusted publishing checks who published something, but it doesn’t check if that person actually meant to publish it. Right now, that difference is the most important thing for supply chain security.

What Just Happened

You probably already know that Axios was compromised at the end of March. Someone published a malicious version with a remote access trojan to npm. The impact was huge because Axios is downloaded millions of times every day and is used in many build systems, CLIs, and production apps.

The details are now public and they matter. Axios maintainer Jason Saayman confirmed this was a targeted social engineering attack. The attacker pretended to be a real company, built trust on a fake Slack workspace, and eventually tricked him into installing malware that gave them full access to his computer.

After that, they did what any attacker would do. They took over his active browser sessions, including cookies and tokens, and used them to publish. Here’s what Saayman said:

“The attacker had enough access to hijack from my browser… lifting sessions or cookies.”

Think about that for a moment. This wasn’t a password leak or a stolen API key. It was a live, authenticated session on the maintainer’s own laptop. The attacker wasn’t just pretending to be the maintainer. As far as npm, GitHub, or any publishing system could tell, they actually were the maintainer.

And I’m Not Speaking Theoretically

I’ve been following the Axios story closely because I very nearly became part of it.

The same campaign targeted me. It followed the same steps: a Slack invitation from what looked like a real company, a convincing pitch, and then a request to download and install “review software.” I didn’t do it. I was busy and the request felt a bit strange. But honestly, if I’d had more time that day, I might have clicked it. These attacks are very well planned.

Here are a few red flags that tipped me off: The Slack invite came from a domain I did not recognize, from someone that I did not know. The conversation was a little too professional and urgent compared to typical outreach. The "review software" they asked me to install was sent as a direct download link rather than through a known app store or repository. Finally, they were oddly persistent in following up, pushing for immediate action. Looking back, these are exactly the kinds of signals that maintainers should watch for.

In fact, so many other high-impact Node.js maintainers were targeted in the same campaign — Feross Aboukhadijeh (WebTorrent, StandardJS, Socket.dev CEO), Jordan Harband (dozens of core polyfills), John-David Dalton (Lodash), Scott Motte (dotenv), Wes Todd (Express TC), and others. If you maintain a package with more than a hundred million weekly downloads, congratulations: you’re on a list somewhere.

The Problem with Provenance

This brings us to npm “trusted publishing” and Provenance.

The idea sounds simple and appealing. npm uses Sigstore to cryptographically confirm that a certain package version was built and published by a specific identity on a certain CI platform. When you run npm audit signatures, npm checks those provenance records. Packages with provenance get a checkmark on the website. The promise is that you can trust these packages because you know who published them.

Here’s the problem: in the Axios case, provenance would have attested to exactly the right person.

It wasn’t a fake account or a stolen password from a data breach. The attacker took over the maintainer’s existing, authenticated session. If Axios had used trusted publishing with OIDC from GitHub Actions, the malicious release would have been signed and confirmed by the real maintainer’s identity, because the attacker was acting as them.

Provenance answers: “Did this come from who it says it came from?”

It does NOT answer: “Is the person who published this in control of their own actions?”

The OpenAI Fallout

The consequences weren’t theoretical. The compromised Axios version made its way into OpenAI’s macOS signing pipeline. A GitHub Actions workflow used in their app-signing process downloaded the malicious Axios, forcing OpenAI to rotate code-signing certificates for ChatGPT Desktop, Codex, and Atlas. Older app versions will stop functioning after May 8.

OpenAI identified the root cause as a CI misconfiguration: a floating tag instead of a pinned commit hash, and no minimumReleaseAge for new packages. This is important. Even a company with mature security practices was exposed because its build system automatically pulled the latest version of a dependency. The provenance of that dependency? Valid. It came from npm. It came from the right publisher. It was just malicious.

What We Actually Need

I’m not saying provenance is bad. Being able to check where a package came from is helpful. But it’s just one part of the solution, not the whole answer. Right now, the ecosystem treats provenance attestation as if it’s a strong security control against the attacks we’re seeing, but it isn’t.

What we’re seeing now is identity-level compromise. The attacker isn’t just pretending to be the maintainer; they actually become the maintainer. In this situation, provenance is worse than useless because it gives a malicious package a trustworthy signature and makes it look credible.

So what would actually help?

First, we need delay windows for new releases. npm, starting with 11.11.0, supports and encourages a configurable minimumReleaseAge, a waiting period before a new version appears in the default registry. This gives security researchers, automated scanners, and CI systems time to catch compromised releases before they reach production. This was originally proposed by pnpm in v10.16.0https://pnpm.io/settings#minimumreleaseage. OpenAI could have avoided its issue with something as simple as this.

Second, we need machine compromise detection. For example, npm could flag if a maintainer publishes a new version from a device they’ve never used before, using a session created in the last hour, in a different timezone, or while also logged into GitHub from a different IP. These checks already exist in enterprise security and fraud detection, and they should be used in open source publishing too.

Third, we need dual-control publishing. For high-impact packages, such as those in the top 0.1 percent of downloads, no single maintainer should be able to publish alone. A second maintainer should review and approve releases through a signed attestation, not just a GitHub PR. This would have stopped the Axios compromise from reaching npm.

But what about solo maintainers or small teams? Those are the typical “Nebraska” project. In these cases, strict dual control might seem impossible. However, those projects already pose a risk to the ecosystem. We all know each other, and we can do better once a module becomes so widespread.

Fourth: we need to stop pretending that “trust the publisher” is sufficient. Every major supply chain attack of the past five years — xz utils, the ESLint-scope incident, and now Axios — follows a similar pattern: compromise the maintainer, publish as the maintainer, watch the malware spread with the full credibility of the maintainer’s reputation and the package ecosystem’s validation infrastructure.

The basic idea behind open source publishing assumes that good actors with compromised devices are no longer a problem. But that’s not true. In fact, this is the main problem we face right now.

The Bottom Line

I’m not against provenance. I’m against the idea that provenance means safety. Right now, provenance tells you “this package was published by Jason Saayman.” It does not, and cannot, tell you “Jason Saayman was in control of his own machine when he hit publish.”

That difference is what caused a package with millions of daily downloads to be compromised, targeted dozens of other maintainers (including me), and forced a certificate rotation at one of the best-resourced software companies in the world.

Until we design our publishing systems with the idea that maintainer identity can be compromised, we’ll keep building security theater instead of real security.

As usual, let me know what you think.

Don't miss what's next. Subscribe to Adventures in Nodeland:
Share this email:
Share on Twitter Share on LinkedIn
GitHub
Twitter
YouTube
LinkedIn