Skip to content

Commit 4e6e2bc

Browse files
committed
security(release): drop .npmrc NPM_TOKEN write, rely on npm trusted publishing
The previous publish flow wrote a static `_authToken` from the `NPM_TOKEN` secret into `~/.npmrc` before invoking `pnpm publish`. On pnpm < 11.0.7 a configured `_authToken` takes precedence over OIDC trusted publishing, so even though all `@rspack/*` packages have a trusted publisher binding configured on npmjs.com, releases were still authenticating with a long-lived token. The static-credential surface is exactly what enables the TanStack 2026-05-11-style attack: anything that runs in the `npm`/`npm-canary` environment can exfiltrate `process.env.NPM_TOKEN` and publish arbitrary versions. Deleting the `.npmrc` write makes OIDC the only auth path. `pnpm publish` now mints a per-run token via the workflow's `id-token: write` permission and authenticates against the trusted publisher binding configured on npmjs.com. Provenance (`--provenance` flag) is unaffected; it was already using OIDC for signing and is independent of publish auth. After merge, the `NPM_TOKEN` secret in the `npm` and `npm-canary` GitHub environments has no remaining consumer and should be removed from environment secrets to fully retire the credential.
1 parent 259b48a commit 4e6e2bc

1 file changed

Lines changed: 0 additions & 12 deletions

File tree

scripts/release/publish.mjs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ const __dirname = path.dirname(__filename);
1010

1111
export async function publish_handler(mode, options) {
1212
console.log('options:', options);
13-
const npmrcPath = `${process.env.HOME}/.npmrc`;
1413
const root = process.cwd();
1514
const version = await getLastVersion(root);
1615
const name = await getPkgName(root);
@@ -26,17 +25,6 @@ export async function publish_handler(mode, options) {
2625
throw Error('Latest tag cannot be prerelease version');
2726
}
2827

29-
if (fs.existsSync(npmrcPath)) {
30-
console.info('Found existing .npmrc file');
31-
} else {
32-
console.info('No .npmrc file found, creating one');
33-
34-
fs.writeFileSync(
35-
npmrcPath,
36-
`//registry.npmjs.org/:_authToken=${process.env.NPM_TOKEN}`,
37-
);
38-
}
39-
4028
await publish(options);
4129

4230
core.setOutput('version', version);

0 commit comments

Comments
 (0)