Skip to content
Back to skills

Npm Trusted Publishing

ASecurity

Publish npm packages via GitHub Actions with OIDC trusted publishing and provenance. Use when setting up automated npm publishes, debugging ENEEDAUTH/E404 errors, configuring provenance attestations, or setting up a new package for publication.

  • 8 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 6, 2026
securityrustgobashnodedebugginggitci/cdsecurity

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 2 files and shows the line behind each finding

Scanned September 6, 2026

npx -y skills add v1truv1us/ai-eng-system --skill npm-trusted-publishing --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Npm Trusted Publishing?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Npm Trusted Publishing
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/v1truv1us-npm-trusted-publishing-82a24186/badge)](https://www.skillsdirectory.com/skills/v1truv1us-npm-trusted-publishing-82a24186)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: npm-trusted-publishing
description: Publish npm packages via GitHub Actions with OIDC trusted publishing and provenance. Use when setting up automated npm publishes, debugging ENEEDAUTH/E404 errors, configuring provenance attestations, or setting up a new package for publication.
metadata:
  category: user-invoked
  version: 2.0.0
disable-model-invocation: true
---

Default output: return only the result, blockers, and required evidence. Omit preambles, process narration, repeated context, confidence scores, and follow-up offers. Use at most five bullets unless a required artifact or schema needs more.

# npm Trusted Publishing

Publish npm packages from GitHub Actions without long-lived tokens. Uses OIDC
for authentication and generates provenance attestations automatically.

## How It Works

1. GitHub Actions workflow runs on tag push
2. Workflow requests short-lived OIDC token from GitHub
3. npm exchanges OIDC token for publish token via registry
4. Package publishes with provenance attestation (supply-chain security)
5. No `NPM_TOKEN` secret needed — ever

## Prerequisites

### npmjs.org (one-time per package)

1. Go to https://www.npmjs.com/settings/
2. Packages → your package → Settings → Trusted publishing
3. Provider: GitHub Actions
4. Organization or user: matches GitHub username exactly (case-sensitive)
5. Repository: matches repo name exactly (case-sensitive)
6. Workflow filename: `publish.yml` (exact — not `publish.yaml`)
7. No environment name unless using GitHub deployment environments

### package.json

```json
{
  "name": "@scope/package-name",
  "version": "1.0.0",
  "repository": {
    "type": "git",
    "url": "https://github.com/user/repo"
  },
  "publishConfig": {
    "access": "public"
  }
}
```

Requirements:
- `repository.url` matches `https://github.com/<user>/<repo>` (no `.git` suffix)
- Package must be public (private packages cannot use provenance)
- Repository must be public (private repos cannot generate provenance)

## Complete Working Workflow

```yaml
name: Publish to npm

on:
  push:
    tags:
      - 'v*'
  workflow_dispatch:
    inputs:
      version:
        description: 'Version to publish'
        required: true
        type: string
      dry_run:
        description: 'Dry run'
        required: false
        type: boolean
        default: false

permissions:
  contents: read
  id-token: write

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '24'
          registry-url: 'https://registry.npmjs.org'

      - name: Install dependencies
        run: npm install

      - name: Build
        run: npm run build

      - name: Publish to npm
        if: <!-- not a dry run -->
        run: npm publish --access public --provenance
```

## Node Version Note

| Node | Bundled npm | Trusted publishing |
|------|-------------|-------------------|
| 18.x | 9.x | ❌ Not supported |
| 20.x | 10.x | ❌ Not supported |
| 22.x | 10.x | ❌ Use `npx npm@11 publish` |
| 24.x | 11.x | ✅ Works directly |
| 26.x | 11.x | ✅ Works directly |

**For Node 20/22:** Use `npx npm@11 publish` instead of `npm publish`.

## Multi-Package Workspaces

For monorepos with multiple publishable packages:

```yaml
- name: Publish core
  working-directory: ./packages/core
  run: npm publish --access public --provenance

- name: Publish toolkit
  working-directory: ./packages/toolkit
  run: npm publish --access public --provenance
```

## Dry Run

Test without publishing:

```yaml
- name: Dry run
  run: npm publish --dry-run --access public --provenance
```

## Provenance Verification

After publish:

```bash
# Confirm version is live
npm view @scope/package version

# Confirm provenance attestation exists
npm view @scope/package dist.attestations.provenance

# View full provenance details
npm view @scope/package --json | jq '.dist.attestations'
```

On npmjs.com package page, look for the **"Provenance"** badge.

## Debugging Failed Publishes

### Check npm version
```bash
npm --version  # Must be 11.x for trusted publishing
```

### Check OIDC env vars
```yaml
- run: |
    echo "ACTIONS_ID_TOKEN_REQUEST_URL: ${ACTIONS_ID_TOKEN_REQUEST_URL:+set}"
    echo "ACTIONS_ID_TOKEN_REQUEST_TOKEN: ${ACTIONS_ID_TOKEN_REQUEST_TOKEN:+set}"
```

### Check trusted publisher config
- Org/user, repo, and workflow filename are all **case-sensitive**
- npm does NOT validate the config on save
- Must match exactly: `https://github.com/Org/Repo` vs `https://github.com/org/repo`

### Common errors

| Error | Cause | Fix |
|-------|-------|-----|
| `ENEEDAUTH` | No `registry-url` in setup-node | Add `registry-url: 'https://registry.npmjs.org'` |
| `404 Not Found` | npm 10.x with trusted publishing | Use Node 24+ or `npx npm@11 publish` |
| `403 Forbidden` | Trusted publisher mismatch | Check case-sensitive org/repo/workflow |
| `EPUBLISHCONFLICT` | Version already exists | Bump version or check if already published |

## Security Best Practices

- ✅ Use `permissions: id-token: write` (minimal)
- ✅ No `NPM_TOKEN` secret needed
- ✅ No `--provenance` flag needed (automatic on GitHub Actions)
- ❌ Never commit `.npmrc` with auth tokens
- ❌ Never use `secrets.NPM_TOKEN` in workflow
- ❌ Never use long-lived publish tokens

## Related

- `ci-cd-and-automation` — General CI/CD patterns
- `shipping-and-launch` — Pre-launch checklists
- `security-and-hardening` — Secrets management

Files in this skill

  • SKILL.md5.4 KB
  • evals/evals.json1.7 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…