Valid provenance, malicious package: what npm trusted publishing does and doesn't protect your agents from
No: npm trusted publishing does not mean a package is safe for an agent to install. Trusted publishing replaces long-lived publish tokens with short-lived OIDC credentials, and the provenance attestation it generates proves where and how a package was built. npm's own documentation says provenance "does not guarantee the package has no malicious code" (npm Docs). In 2026 one major compromise shipped without provenance, by bypassing the pipeline with a stolen token, and another shipped with valid SLSA Build Level 3 provenance. Use provenance as a signal that changes scrutiny, never as an allow verdict.
The consensus, stated fairly
After the Shai-Hulud worm of September 2025, which led GitHub to remove more than 500 compromised packages, GitHub laid out a plan for npm: granular tokens with a seven-day lifetime, deprecation of classic tokens, expanded trusted publishing, publishing that disallows tokens by default, and FIDO-based two-factor authentication (GitHub, 22 September 2025). Trusted publishing is the centrepiece. A maintainer links a package to a CI workflow, and from then on the registry accepts releases from that workflow using an identity token minted for one run (npm Docs).
The reasoning behind treating this as the fix is sound as far as it goes. Most large npm compromises have started with a stolen maintainer credential. Remove the stored credential and you remove the most common entry point. A provenance badge then looks like a certificate that the entry point was closed for this release.
That last step is where the reasoning breaks. A certificate of origin is being read as a certificate of intent.
The cracked assumption: origin is not intent
Provenance answers two questions. Which source repository and build instructions produced this artifact, and which identity published it. npm describes it as "a verifiable link to the package's source code and build instructions." Those are useful facts. They are not the question an agent's install policy needs answered, which is whether the code will do something harmful when installed.
Two 2026 incidents show the gap from opposite directions.
Case one: the release that skipped the pipeline
axios is a useful case because its registry metadata is public. Registry records retrieved for this article on 15 October 2026 show that [email protected], published on 27 March 2026, was published by "GitHub Actions" through a trusted-publisher binding and carries an SLSA provenance attestation. [email protected], published at 00:21 UTC on 31 March, was not. StepSecurity found that the malicious release had no trusted-publisher binding and no gitHead, had no matching commit or tag in the repository, and was published with stolen credentials outside the GitHub Actions pipeline; it infers a long-lived classic npm token was used (StepSecurity).
Trusted publishing was in place for the 1.x line. It did not stop the attack, because a token could still publish. Sources describe this differently: Aikido's August analysis says axios "hadn't adopted Trusted Publishing" before the compromise (Aikido, 24 August 2026), while the registry record and StepSecurity show 1.x releases already going through a trusted-publisher binding. The reading consistent with both is that trusted publishing was in use but token publishing had evidently not been switched off.
There is a second detail in the registry data. The previous 0.x release, [email protected], has no provenance attestation at all. A policy that flagged "provenance disappeared since the last version" would have caught 1.14.1 and missed 0.30.4, published 39 minutes later from the same account.
Case two: valid provenance on a malicious build
Aikido reports that during the Mini Shai-Hulud II / TanStack campaign of 7-11 May 2026, attackers poisoned a GitHub Actions cache, extracted the OIDC token from runner memory, and published more than 170 packages across npm and PyPI in five hours. "The published packages carried valid SLSA Build Level 3 provenance attestations." The pipeline was trusted. The pipeline was compromised. The attestation was true.
The adoption gap
Even as a token-theft control, trusted publishing covers a minority of what agents install. Aikido counts 11,001 of the top 51,370 npm packages publishing through trusted publishing, about 25% of download volume, with 40,369 packages, about 75% of download volume, still on long-lived tokens. Aikido does not disclose how the top packages were selected or when the data was collected, and adoption figures move monthly, so treat these as a snapshot. The direction is clear enough: most installs an agent performs today come from packages where a stolen token still publishes.
The alternative mechanism in one sentence
Treat provenance as evidence about the publishing path, compare it with the package's own history, and let a change in that path raise scrutiny, while the decision about intent comes from known-bad data, release age and behaviour.
What provenance proves, and what it does not
Question an install policy asks Does provenance answer it?
---------------------------------------------------- ------------------------------------------------
Was this built from the named public repository? Yes, for attested releases
Which CI workflow and identity published it? Yes, for attested releases
Was a stored long-lived token used to publish? Only by absence: no attestation, no OIDC binding
Did the publishing path change since last release? Yes, if you compare with the previous version
Is the code free of malicious behaviour? No. npm: "does not guarantee" it
Was the CI pipeline itself uncompromised? No (TanStack: valid SLSA L3 on malicious builds)
Is this package already reported as malicious? No. That is a separate advisory dataset
Has the release been public long enough to be No. That is release age, a separate check
scrutinised?
Consumers can verify attestations on installed packages with npm audit signatures, which npm documents as verifying provenance attestations from npm CLI 9.5.0 onward.
Using provenance in an agent install policy
Four rules capture what provenance can do without overclaiming.
- Provenance regression raises scrutiny. If the previous release of a package was attested and this one is not, route the install to block or human review. This would have flagged
[email protected]. - Provenance present does not allow. An attested release still goes through the known-bad check and the release-age delay. This is the TanStack lesson.
- Provenance absent is unknown, not bad. Most packages are not attested yet. Blocking on absence alone blocks most of the ecosystem and trains people to override the rule.
- Log the attestation state with every decision. When an incident happens, you will want to know which installs relied on which publishing path.
Where the consensus still wins
Trusted publishing does remove a real attack path. A package whose maintainers have both enabled it and disabled token publishing cannot be released with a stolen token at all, which closes the axios route entirely. npm's documentation recommends exactly that: after enabling trusted publishers, select "Require two-factor authentication and disallow tokens." Maintainers reading this should do it today. The criticism here is of how consumers read the badge, not of the mechanism.
A note for maintainers
If you publish packages that agents install, the axios case gives a short checklist, every item of which comes from npm's or GitHub's own guidance.
- Configure a trusted publisher for each package, from a GitHub-hosted, GitLab.com shared or CircleCI cloud runner; npm does not currently support self-hosted runners for this.
- Publish from a public repository if you want automatic provenance; npm does not generate it for private repositories or for CircleCI publishes.
- In the package's publishing-access settings, choose "Require two-factor authentication and disallow tokens." Until this step is done, a stolen token still publishes, which is exactly what happened to axios.
- Revoke classic tokens you no longer need. GitHub's plan deprecates them and limits granular tokens to a seven-day lifetime.
- Treat the CI workflow that publishes as production infrastructure. The TanStack case shows that a compromised workflow produces valid attestations.
Consumers benefit from step 3 more than from any badge, because it removes the publishing path the provenance check was trying to detect.
Where this argument would be wrong
If registries began refusing token publishes for every package that has ever used trusted publishing, case one would stop recurring. If CI providers closed the runner-memory route used in case two, attested releases would become much harder to forge from inside a pipeline. Either change would make a provenance check a stronger input. Neither would make it a statement about intent.
The Monday decision: find every place in your CI or agent policy where "has provenance" maps to "allow," and change it to "continue to the next check."
For the next check, the threat.cafe list tracks known-bad agent artifacts and packages across registries, with sources.
Sources
- Generating provenance statements — npm Docs, accessed 15 October 2026
- Trusted publishing for npm packages — npm Docs, accessed 15 October 2026
- Our plan for a more secure npm supply chain — GitHub, 22 September 2025
- axios Compromised on npm - Malicious Versions Drop Remote Access Trojan — StepSecurity, March 2026
- Shai-Hulud was the best thing to happen to supply chain security — Aikido, 24 August 2026
- axios package metadata — npm registry, retrieved 15 October 2026