ci: publish to npm via trusted publishing (OIDC), not a 2FA-bypass token - #11
Merged
Conversation
The publish job authenticated with secrets.NPM_TOKEN. Automation tokens bypass 2FA by design — that's their whole purpose — so the strongest account protection did not cover the one operation that matters most: shipping code to everyone who runs `npm i -g gitflare`. A leaked token publishes a release on its own. Trusted publishing removes the standing credential entirely. GitHub mints a short-lived OIDC credential scoped to a single workflow run, and npm verifies it against a publisher registered for this repo + this exact workflow filename. Nothing to exfiltrate, nothing to rotate. - id-token: write on the publish job only (release-please doesn't need it) - Node 22 + npm@latest in the publish job: OIDC needs Node >= 22.14 and npm >= 11.5.1, and Node 22 still bundles npm 10.x. ci.yml stays on Node 20 so the engines >= 20 floor is still tested. - NODE_AUTH_TOKEN dropped; the npm CLI detects OIDC on its own. Side benefit: npm generates provenance attestations automatically for public packages published this way, so releases become verifiable back to this repo and commit. REQUIRES a one-time setup on npmjs.com before this merges — see the PR. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Merging this before the trusted publisher is registered on npmjs.com will break the next release publish — the workflow will have no token and no registered publisher.
The problem
The publish job authenticated with
secrets.NPM_TOKEN. npm automation tokens bypass 2FA by design — that is what they are for. So the account's strongest protection did not cover the single most sensitive operation in the repo: shipping code to everyone who runsnpm i -g gitflare. Anyone holding that token publishes a release on their own, with no second factor in the way.This is also on a clock: bypass-2FA tokens stop working for publishing in January 2027, when npm moves publishing to OIDC.
The fix
Trusted publishing removes the standing credential entirely. GitHub mints a short-lived OIDC credential scoped to one workflow run; npm verifies it against a publisher registered for this repo and this exact workflow filename. Nothing to exfiltrate, nothing to rotate, nothing that works outside a run of this workflow.
Workflow changes:
id-token: writeon the publish job only —release-pleasedoesn't need it.npm install -g npm@latestin the publish job. OIDC needs Node >= 22.14 and npm >= 11.5.1, and Node 22 still bundles npm 10.x.ci.ymlstays on Node 20 so theengines: >=20floor is still tested.NODE_AUTH_TOKENdropped; the npm CLI detects the OIDC environment itself.Side benefit: npm generates provenance attestations automatically for public packages published this way, so releases become cryptographically traceable back to this repo and commit.
Rollout — order matters
gitflarepackage → Settings → Trusted Publisher. GitHub Actions; org/usersinameraji; repositorygitflare; workflow filenamerelease-please.yml; no environment. All fields are case-sensitive and must match exactly.gitflare→ Settings → Publishing access → "Require two-factor authentication and disallow tokens." Trusted publishing keeps working — that setting only blocks traditional token auth.NPM_TOKENfrom the repo's Actions secrets, and revoke the token itself at npmjs.com → Access Tokens.Step 4 is what actually closes the hole; steps 1–3 just make sure releases still ship when it does. Step 5 makes it irreversible.
Caveat worth knowing
The trusted publisher pins the workflow filename. Renaming
release-please.ymlbreaks publishing until the registration is updated — noted in a comment on the job.🤖 Generated with Claude Code