Conversation
|
|
@ljharb 👋
I've thought about this a lot. I also want this, but I question its necessity. If you have
Not really possible. The whole point of OIDC is to have a trusted publisher (like GitLab or GitHub) as the issuer of a token that the registry trusts. A local machine isn't a trusted issuer, so we wouldn't be able to validate any token you could provide. |
|
Right, but what if an attacker configures OIDC on npmjs.com unbeknownst to me? I'd still want to ensure CI can't publish with it. So to clarify, the reason it's not possible is because the npm servers only have a finite hardcoded list of "trusted OIDC publishers", and i'm not on it? |
80c39ba to
3a930c9
Compare
wraithgar
left a comment
There was a problem hiding this comment.
So clean, so boilerplate. Let's leave this unmerged for at least a little while to see if any more community input happens.
If an attacker has access to your npmjs.com account, they can just make gat tokens, I think OIDC would be the least of your worries 🤔 . Further expanding on this idea if a malicious actor got access to your account and added a trusted connection to one of THEIR repos, with their own workflow a
Yeah, kinda |
|
Just to chime in, I'm onboard and supportive w/ the decision to avoid a cli parameter here for the sake of feature streamlining. Security wise, the malicious access goes similarly to creating access tokens, as mentioned above.
By finite we are kick starting this feature w/ 2 trusted publishers: GitHub Actions and GitLab. This is an MVP and we want to understand the usage feedback for the next iterations on this feature. If possible, I'd really love if we can shift other feature requests and feedback at the community discussion post as it makes it easier for me to track feedback received and we keep this PR limited to new changes added to the repo. |
#8399) Co-authored-by: Chris Sidi <hashtagchris@github.com>
I don't believe we need to destructure the objects as we we're doing.
|
I feel like this logic should not be in the npm CLI, but rather a part of |
This PR adds "auto" or "default" provenance to publishes that use OIDC within github and gitlab. It does this by checking the OIDC id token payload and checking if the current repo's visibility is public or private if it's public we do the equivalent of adding the `--provenance` flag.
small update to allow gitlab to NOT REQUIRE provenance
The runner's bundled npm (10.9.8, shipped with Node 22) predates npm/cli#8336 which added OIDC token exchange support (npm 11.4.2), so --provenance was silently ignored and publish failed with ENEEDAUTH. Upgrade npm before publishing.
Prerequisite for trusted publishing, landed separately and ahead of it on purpose. The runner's Node 22.23.2 bundles npm 10.9.8 — measured in run 33201098721 — and OIDC publish support arrived in npm 11.5.0 (npm/cli#8336, 2025-07-24). The ordering is the point. Registering a trusted publisher on npmjs.com while the runner still had npm 10 would look like the REGISTRATION had failed: npm 10 does not attempt OIDC at all, so it would quietly authenticate with NODE_AUTH_TOKEN and publish green by the old path, with nothing in the log saying which mechanism ran. Raising the floor first makes the switch a one-line change instead of a debugging session. Nothing changes today: with a token present and no trusted publisher registered, npm 11 authenticates exactly as npm 10 did. This push exercises the new step for free — 1.1.1 is already on the registry, so `already published?` short-circuits and the run is a green no-op. Why this matters now: bypass-2FA granular tokens lose direct publish in January 2027 (github.blog changelog 2026-07-31), and this repo's token expires 2026-11-26. Trusted publishing removes the credential rather than rotating it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Adds id-token: write to the release workflow and forces npm to a version >=11.5.1 right after actions/setup-node, since pnpm publish shells out to whatever npm is first on PATH (see pnpm's exec/run-npm) rather than bundling its own, and OIDC trusted publishing requires that npm version. This is additive, not a cutover: npm's OIDC detection gracefully falls back to NODE_AUTH_TOKEN/NPM_TOKEN when a package has no trusted publisher registered (confirmed against the source PR, npm/cli#8336), so every package keeps publishing exactly as before until its trusted publisher is configured. RELEASE.md documents the one part that needs a human: registering a trusted publisher per package on npmjs.com (repo/workflow-filename/org — can't be done via API, needs an npm web session), plus how to verify OIDC actually took over per package, and the known pnpm+OIDC intermittency (pnpm/pnpm#11513) this setup works around. Also fixes a pre-existing README bug while touching this section: `pnpm version` collides with pnpm's own built-in version-bump command, so the documented command silently ran the wrong thing. Needs `pnpm run version` (release.yml already did this correctly). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The trusted publisher on npm was already configured correctly. The retagged
js/v0.3.0 run got past every other step -- including the real test-ordering
fix -- and failed here, on a response body that plainly carried a real,
freshly issued token:
{"created":1788421934,"expires":1788422834,"token":"***","token_type":"oidc"}
That is a success shape, and the step reported it as npm refusing the
exchange, because it checked `[ "$code" != "200" ]` and the registry did not
return exactly 200.
npm's own CLI (npm/cli#8336) settles what the real contract is: it does not
check the HTTP status code for this exchange at all. It decides success or
failure purely by whether the parsed JSON body has a `token` field. This step
now does the same, rather than a workflow here guessing which 2xx code the
registry uses for "created" a token.
Verified against both bodies actually seen from this registry: the real
success body above returns "yes", and a real refusal body,
{"error":"invalid-publisher"}, returns "no". YAML and embedded shell both
syntax-checked.
🎉 Introducing OIDC Support for npm Publishing!
We're thrilled to announce a new security feature that makes publishing npm packages from CI environments easier and more secure! This PR adds OpenID Connect (OIDC) token support for npm publishing, which eliminates the need to store long-lived access tokens in CI secrets.
With OIDC support, you can now publish packages from GitHub Actions and GitLab CI with improved security through short-lived, automatically generated tokens. This is a major step forward in securing the npm ecosystem and simplifying CI/CD workflows.
Technical Details
This implementation adds OIDC token support by:
The feature is designed to be non-invasive - it only activates in CI environments and gracefully falls back to traditional authentication methods when OIDC isn't available.
For Publishers
Updating Package Settings on npmjs.com
Warning
Not live yet, OIDC support is currently under development. The CLI,
npmjs.com, and registry changes will be rolled out incrementally. Stay tuned for a public preview announcement. As of now, this documentation reflects features planned for a future release.Important
In order to use OIDC publishing, a package must already exist on npmjs.com. This means the initial publish needs to be done through conventional means; further publishes, once configured, can use OIDC.
Before using OIDC for publishing, ensure your package settings on npmjs.com are configured to allow CI/CD workflows.
This step ensures that your package is ready to accept tokens generated via OIDC workflows.
GitHub Actions
To publish with OIDC from GitHub Actions:
id-token: writepermission to your workflow:NPM_TOKENsecrets anymore! Just run npm publish as usual:GitLab CI
To publish with OIDC from GitLab CI:
NPM_ID_TOKENenvironment variable:For other CLI's
If you're building a CLI tool that publishes to npm registries, you can implement OIDC support by:
ACTIONS_ID_TOKEN_REQUEST_URLendpoint with the proper audience format (npm:registry.hostname)NPM_ID_TOKENenvironment variable if availableFor other Registries
As a registry, you'll need a way for package publishers to create connections between OIDC Trusted Publishers and the registry, similar to how we allow connections to be added on the package settings page of npmjs.com.
To support OIDC token authentication in your npm-compatible registry:
Implement an endpoint at
/-/npm/v1/oidc/token/exchange/package/${escapedPackageName}that accepts POST requests (no body) withAuthorizationheader /Bearerset to thejwt-token-from-ci-provider.Verify the OIDC token using standard JWT validation practices, checking the audience claim matches your expected format (
npm:your.registry.hostname)Return a response with a short-lived npm token:
{ "token": "npm_short_lived_token" }Technical Overview
oidc.jshandles:publishcommand →libnpmpublishmodule →npm-registry-fetchKey touchpoints:
This initial implementation is focused on the publish workflow only. Currently OIDC token support is limited to the publish command.