From f8e542efbfb2cbb94f73cd5e8eff3a1767a69cb5 Mon Sep 17 00:00:00 2001 From: Rob Bos Date: Sat, 9 May 2026 13:27:39 +0200 Subject: [PATCH 1/3] fix(ci): use NPM_TOKEN secret for npm publish auth NODE_AUTH_TOKEN was explicitly set to empty string, which overrode the auth configured by setup-node and caused ENEEDAUTH failures. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/cli-publish.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cli-publish.yml b/.github/workflows/cli-publish.yml index 20f2ef6c..71db5f93 100644 --- a/.github/workflows/cli-publish.yml +++ b/.github/workflows/cli-publish.yml @@ -125,11 +125,15 @@ jobs: - name: Publish to npm if: ${{ !inputs.dry_run && steps.check_published.outputs.already_published != 'true' }} - run: NODE_AUTH_TOKEN="" npm publish + run: npm publish --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - name: Dry run publish if: ${{ inputs.dry_run }} - run: NODE_AUTH_TOKEN="" npm publish public --dry-run + run: npm publish --access public --dry-run + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - name: Commit version bump and create PR if: ${{ !inputs.dry_run && steps.check_published.outputs.already_published != 'true' && steps.trigger_type.outputs.is_tag != 'true' }} From af368f18a9431c4a292438e6dc6e50b4ed75a285 Mon Sep 17 00:00:00 2001 From: Rob Bos Date: Sat, 9 May 2026 13:31:07 +0200 Subject: [PATCH 2/3] fix(ci): use OIDC provenance for npm publish Remove NODE_AUTH_TOKEN override (empty string broke auth) and add --provenance flag so npm exchanges the OIDC token automatically. id-token: write permission is already set on the job. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/cli-publish.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/cli-publish.yml b/.github/workflows/cli-publish.yml index 71db5f93..4c5b8175 100644 --- a/.github/workflows/cli-publish.yml +++ b/.github/workflows/cli-publish.yml @@ -125,15 +125,11 @@ jobs: - name: Publish to npm if: ${{ !inputs.dry_run && steps.check_published.outputs.already_published != 'true' }} - run: npm publish --access public - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + run: npm publish --provenance --access public - name: Dry run publish if: ${{ inputs.dry_run }} - run: npm publish --access public --dry-run - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + run: npm publish --provenance --access public --dry-run - name: Commit version bump and create PR if: ${{ !inputs.dry_run && steps.check_published.outputs.already_published != 'true' && steps.trigger_type.outputs.is_tag != 'true' }} From 92278f0c48bfa3a0c338f50516b9fe25e49e3a74 Mon Sep 17 00:00:00 2001 From: Rob Bos Date: Sat, 9 May 2026 13:34:39 +0200 Subject: [PATCH 3/3] docs: document npm OIDC publishing pattern in workflow instructions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../instructions/workflows.instructions.md | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/.github/instructions/workflows.instructions.md b/.github/instructions/workflows.instructions.md index 4b0a9d0b..cd4be3ad 100644 --- a/.github/instructions/workflows.instructions.md +++ b/.github/instructions/workflows.instructions.md @@ -2,6 +2,42 @@ applyTo: ".github/workflows/**" --- +# npm Publishing via OIDC (Trusted Publishing) + +This repository publishes the CLI package to npm using GitHub Actions OIDC trusted publishing — no `NPM_TOKEN` secret is required. + +## Required setup + +1. **Job permission:** `id-token: write` must be set on the publish job. +2. **setup-node:** Use `registry-url: 'https://registry.npmjs.org'` so npm is configured for the registry. +3. **Publish command:** Always include `--provenance` so npm exchanges the OIDC token automatically: + +```yaml +- name: Publish to npm + run: npm publish --provenance --access public +``` + +## Common mistake to avoid + +Do **not** set `NODE_AUTH_TOKEN` to an empty string: + +```yaml +# ❌ WRONG — explicitly clears the token and causes ENEEDAUTH +run: NODE_AUTH_TOKEN="" npm publish + +# ❌ ALSO WRONG — requires a secret that isn't needed +run: npm publish +env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + +# ✅ CORRECT — OIDC token is exchanged automatically via --provenance +run: npm publish --provenance --access public +``` + +Setting `NODE_AUTH_TOKEN=""` overrides the auth that `setup-node` configures and causes `ENEEDAUTH` failures even though `id-token: write` is set. + +--- + # Workflow Security: Validating Untrusted User Input ## Overview