You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm opening this issue just to get more attention from the express side. I opened fastify/fastify#5984 to discuss a feasible approach to rotate npm keys across many repositories of an organization, and I believe the same problem we are facing on fastify would happen here.
@UlisesGascon has mentioned you all would be working on something similar soon, so I thought I could help and we could create something more universal. Where can I get more info about this initiative?
I think the main thing we need to work out is the automated release workflows. This is what @sheplu will be working on as part of our STF funding this year. I have pretty strong opinions on this but probably not yet the time for me to write it up here. I will jot down some basic requirements I think we have though.
2FA support. This is the main thing lacking in the vanilla GHA publish workflows. There is the step-security stuff for this, but I have been hesitant to rely on a 3rd party company for this. Maybe that is an ideal worth giving up on so we can have 2FA?
Release via PR. Each release needs a PR we can review with strong merge restrictions. Ideally this would include generated changelogs and GH releases.
Monorepo support. This one might be considered a "nice to have", but I strongly believe there are some domains of this project which would have benefited from a small monorepo setup. I would not like our release workflow to be a blocker for how we structure the code in the repos.
Thanks for the offer @elliot-huffman! We will be putting together plans in the coming weeks afaik and am sure there will be things which can be helped with. I would suggest starting with finding and engaging in the many existing discussions in our repos and finding where there are already opportunities to contribute, then engaging in a discussion in our Slack (on the OpenJS Slack workspace). As much of this work is funded by the STF I believe there will be more structure around the work than normal so that it can all be reported correctly, so make sure to sync with @sheplu on it as he is leading that milestone.
Yes, migrating to trusted publishing will eliminate the need for any tokens as OIDC based JWT is used. It also auto enables provance at the same time and reduces a single point of failure. The repo itself is now the trust point instead of a single identity with access to NPM.
I have personally migrated ALL of my projects to trusted publishing.
However, trusted publishing doesn't indicate who did the publish (not even in the packument data), and it means you're trusting github's 2FA alone, instead of also requiring npm's 2FA.
I understand the importance of the packument in surfacing publisher metadata — and I’m not suggesting we eliminate it. But I do think we should be cautious about relying on it as the sole source of truth. It’s not cryptographically verifiable, and it doesn’t inherently provide a tamper-proof trail of how a package was built and published.
Instead, I believe the packument could be complemented by provenance metadata — ideally linked to GitHub Actions workflows and environments. This would allow consumers to verify not just who published a package, but how it was built and approved, with cryptographic guarantees.
The current model (access token-based publishing) lacks:
Cryptographic attestation
Multi-factor authentication (OIDC provides this for services)
Centralized identity control (SSO/IDP integration)
Approval gates and audit trails tied to source control
By shifting the source of truth to GitHub Actions and environments, we get:
SLSA Level 3 compliance
Cryptographic proof of integrity
Credential-less publishing
Public auditability (for public repos)
This isn't just about security — it's about trust and traceability. If the goal is to know who published and what was published, GitHub provenance gives us both, and could be surfaced alongside packument data for full transparency.
Would love to hear thoughts on how we could evolve the ecosystem to support this kind of layered trust model!
P.S. I can't find NPM/GitHub docs on packument, only 3rd party package stuff on it. Do you happen to have a link to the docs? I would love to learn more about it.
"Cryptographically verifiable" isn't interesting - anything in a packument is eternally immutable and always has been, and that's more than sufficient.
Verifying the security of things on npm shouldn't require any external service, including GitHub or sigstore etc.
I looked at the NPM Package metadata using the npm show express --json and I did not see anything that indicated that it was truly Wesly Todd that published the package. Anyone with his token can publish as him and we could not prove otherwise.
Also, can you provide references to prove your points?
I am seeing only "trust me" arguments.
For example, I provided https://slsa.dev, which is peer reviewed work from the Linux foundation.
P.S.
Thank you for the npm view foo --json command, that is interesting metadata.
npm show express time will list who published each version, and npm show express _npmUser will show the contents of that field on the packument. If you check a package that's used trusted publishing, eg npm show @rsbuild/core _npmUser, you'll see it only shows GitHub Actions <npm-oidc-no-reply@github.com>.
(yes, i'm familiar with SLSA; i've been on the OpenSSF board in the past)
Activity
[-]Universal Action to rotate NPM token keys[/-][+]Universal Action to rotate NPM keys[/+]wesleytodd commentedon Feb 17, 2025
I think the main thing we need to work out is the automated release workflows. This is what @sheplu will be working on as part of our STF funding this year. I have pretty strong opinions on this but probably not yet the time for me to write it up here. I will jot down some basic requirements I think we have though.
step-securitystuff for this, but I have been hesitant to rely on a 3rd party company for this. Maybe that is an ideal worth giving up on so we can have 2FA?RafaelGSS commentedon Feb 17, 2025
Thanks for the summary @wesleytodd. @sheplu happy to discuss this with you!
elliot-huffman commentedon Feb 19, 2025
What level of engagement would you like from me here?
I can assist with the below security items:
I am personally invested in the security of this project as Express.JS is a critical supply chain item for my projects/apps.
wesleytodd commentedon Feb 19, 2025
Thanks for the offer @elliot-huffman! We will be putting together plans in the coming weeks afaik and am sure there will be things which can be helped with. I would suggest starting with finding and engaging in the many existing discussions in our repos and finding where there are already opportunities to contribute, then engaging in a discussion in our Slack (on the OpenJS Slack workspace). As much of this work is funded by the STF I believe there will be more structure around the work than normal so that it can all be reported correctly, so make sure to sync with @sheplu on it as he is leading that milestone.
bjohansebas commentedon Mar 20, 2025
Most likely related nodejs/package-maintenance#244 and nodejs/package-maintenance#282
Phillip9587 commentedon Sep 29, 2025
Would trusted publishing solve this? https://docs.npmjs.com/trusted-publishers
elliot-huffman commentedon Sep 29, 2025
Yes, migrating to trusted publishing will eliminate the need for any tokens as OIDC based JWT is used. It also auto enables provance at the same time and reduces a single point of failure. The repo itself is now the trust point instead of a single identity with access to NPM.
I have personally migrated ALL of my projects to trusted publishing.
ljharb commentedon Sep 30, 2025
However, trusted publishing doesn't indicate who did the publish (not even in the packument data), and it means you're trusting github's 2FA alone, instead of also requiring npm's 2FA.
elliot-huffman commentedon Sep 30, 2025
From a supply chain trust perspective, GitHub owns NPM: https://www.npmjs.com/about
That is only if you don't use GitHub environments with approval Gates.
Also, OIDC is MFA for service accounts:
Doing this also achieves SLSA Level 3: https://slsa.dev
Other security benefits from moving off of NPM auth to GitHub auth:
With Approval Gates in GitHub Environment, you know exactly who can approve and have an audit log of who has approved.
Audit trail example:

Repo Configuration Example:
Has threat modeling of the deploy systems even been done?
Threat Model Reference:
https://learn.microsoft.com/en-us/azure/security/develop/secure-design#use-threat-modeling-during-application-design
ljharb commentedon Sep 30, 2025
Github audit logs aren't what's needed or what's useful; the packument on npm is what needs to show the publisher.
An audit log that's only available to maintainers doesn't help anything.
elliot-huffman commentedon Sep 30, 2025
Just to clarify — GitHub audit logs are publicly accessible for public repositories. Anyone can inspect the provenance trail if it's configured correctly. This includes the GitHub Actions workflow that built and published the package, along with cryptographic attestation of the source and build integrity.
Please see here for a public example: https://github.com/Software-Hardware-Integration-Lab/Development-Utilities/actions/runs/17807290728
I understand the importance of the packument in surfacing publisher metadata — and I’m not suggesting we eliminate it. But I do think we should be cautious about relying on it as the sole source of truth. It’s not cryptographically verifiable, and it doesn’t inherently provide a tamper-proof trail of how a package was built and published.
Instead, I believe the packument could be complemented by provenance metadata — ideally linked to GitHub Actions workflows and environments. This would allow consumers to verify not just who published a package, but how it was built and approved, with cryptographic guarantees.
The current model (access token-based publishing) lacks:
By shifting the source of truth to GitHub Actions and environments, we get:
This isn't just about security — it's about trust and traceability. If the goal is to know who published and what was published, GitHub provenance gives us both, and could be surfaced alongside packument data for full transparency.
Would love to hear thoughts on how we could evolve the ecosystem to support this kind of layered trust model!
P.S. I can't find NPM/GitHub docs on
packument, only 3rd party package stuff on it. Do you happen to have a link to the docs? I would love to learn more about it.ljharb commentedon Sep 30, 2025
"Cryptographically verifiable" isn't interesting - anything in a packument is eternally immutable and always has been, and that's more than sufficient.
Verifying the security of things on npm shouldn't require any external service, including GitHub or sigstore etc.
elliot-huffman commentedon Sep 30, 2025
Then riddle me this, why is npm/GitHub/Microsoft AND the Linux foundation investing in it and recommending everyone to migrate to it?
Also, please do provide a docs link, I still cannot find what you are referring to as a first party capability.
ljharb commentedon Sep 30, 2025
I really can't explain why large companies sometimes invest time and money and effort into ineffective solutions.
The packument is what shows up when you
npm show foo --jsonfor any given packagefoo.elliot-huffman commentedon Sep 30, 2025
I looked at the NPM Package metadata using the
npm show express --jsonand I did not see anything that indicated that it was truly Wesly Todd that published the package. Anyone with his token can publish as him and we could not prove otherwise.Also, can you provide references to prove your points?
I am seeing only "trust me" arguments.
For example, I provided https://slsa.dev, which is peer reviewed work from the Linux foundation.
P.S.
Thank you for the
npm view foo --jsoncommand, that is interesting metadata.ljharb commentedon Sep 30, 2025
npm show express timewill list who published each version, andnpm show express _npmUserwill show the contents of that field on the packument. If you check a package that's used trusted publishing, egnpm show @rsbuild/core _npmUser, you'll see it only showsGitHub Actions <npm-oidc-no-reply@github.com>.(yes, i'm familiar with SLSA; i've been on the OpenSSF board in the past)