1 ---
2 title: Trusted publishing for npm packages
3 ---
4
5 Trusted publishing allows you to publish npm packages directly from your CI/CD workflows using [OpenID Connect (OIDC)](https://openid.net/developers/how-connect-works/) authentication, eliminating the need for long-lived npm tokens. This feature implements the [trusted publishers industry standard](https://repos.openssf.org/trusted-publishers-for-all-package-repositories) specified by the Open Source Security Foundation (OpenSSF), joining a growing ecosystem including [PyPI](https://docs.pypi.org/trusted-publishers/), [RubyGems](https://guides.rubygems.org/trusted-publishing/), and other major package registries in offering this security enhancement.
6
7 <Note>
8
9 **Note:** Trusted publishing requires [npm CLI](https://docs.npmjs.com/cli/v11) version 11.5.1 or later and Node version 22.14.0 or higher.
10
11 </Note>
12
13 ## How trusted publishing works
14
15 Trusted publishing creates a trust relationship between npm and your CI/CD provider using OIDC. When you configure a trusted publisher for your package, npm will accept publishes from the specific workflow you've authorized, in addition to traditional authentication methods like npm tokens and manual publishes. The npm CLI automatically detects OIDC environments and uses them for authentication before falling back to traditional tokens.
16
17 This approach eliminates the security risks associated with long-lived write tokens, which can be compromised, accidentally exposed in logs, or require manual rotation. Instead, each publish uses short-lived, cryptographically-signed tokens that are specific to your workflow and cannot be extracted or reused.
18
19 ## Supported CI/CD providers
20
21 Trusted publishing currently supports:
22
23 - [GitHub Actions](https://github.com/features/actions) (GitHub-hosted runners)
24 - [GitLab CI/CD Pipelines](https://docs.gitlab.com/ci/pipelines/) (GitLab.com shared runners)
25
26 Self-hosted runners are not currently supported but are planned for future releases.
27
28 ## Configuring trusted publishing
29
30 ### Step 1: Add a trusted publisher on npmjs.com
31
32 Navigate to your package settings on [npmjs.com](https://www.npmjs.com) and find the "**Trusted Publisher**" section. Under "**Select your publisher**", choose your CI/CD provider by clicking either the GitHub Actions or GitLab CI/CD button.
33
34 <Screenshot src="/packages-and-modules/securing-your-code/trusted-publisher.png" alt="Screenshot showing the Trusted Publisher section with Select your publisher label and provider buttons" />
35
36 #### For GitHub Actions
37
38 Configure the following fields:
39
40 - **Organization or user** (required): Your GitHub username or organization name
41 - **Repository** (required): Your repository name
42 - **Workflow filename** (required): The filename of your workflow (e.g., `publish.yml`)
43 - Enter only the filename, not the full path
44 - Must include the `.yml` or `.yaml` extension
45 - The workflow file must exist in `.github/workflows/` in your repository
46 - **Environment name** (optional): If using [GitHub environments](https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment) for deployment protection
47
48 <Screenshot src="/packages-and-modules/securing-your-code/trusted-publisher-github-actions.png" alt="Screenshot of GitHub Actions trusted publisher configuration form" />
49
50 #### For GitLab CI/CD
51
52 Configure the following fields:
53
54 - **Namespace** (required): Your GitLab username or group name
55 - **Project name** (required): Your project name
56 - **Top-level CI file path** (required): The path to your CI file (e.g., `.gitlab-ci.yml`)
57 - Must include the `.yml` extension
58 - **Environment name** (optional): If using [GitLab environments](https://docs.gitlab.com/ee/ci/environments/)
59
60 <Screenshot src="/packages-and-modules/securing-your-code/trusted-publisher-gitlab.png" alt="Screenshot of GitLab CI/CD trusted publisher configuration form" />
61
62 <Note>
63
64 **Note:** Each package can only have one trusted publisher configured at a time.
65
66 </Note>
67
68 ### Step 2: Configure your CI/CD workflow
69
70 #### GitHub Actions configuration
71
72 Add the required OIDC permissions to your workflow. Here's a complete example:
73
74 ```yaml
75 name: Publish Package
76
77 on:
78 push:
79 tags:
80 - 'v*'
81
82 permissions:
83 id-token: write # Required for OIDC
84 contents: read
85
86 jobs:
87 publish:
88 runs-on: ubuntu-latest
89 steps:
90 - uses: actions/checkout@v4
91
92 - uses: actions/setup-node@v4
93 with:
94 node-version: '24'
95 registry-url: 'https://registry.npmjs.org'
96 - run: npm ci
97 - run: npm run build --if-present
98 - run: npm test
99 - run: npm publish
100 ```
101
102 The critical requirement is the `id-token: write` permission, which allows GitHub Actions to generate OIDC tokens. Learn more in [GitHub's OIDC documentation](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect).
103
104 #### GitLab CI/CD configuration
105
106 Configure the OIDC ID token in your pipeline:
107
108 ```yaml
109 stages:
110 - test
111 - build
112 - publish
113
114 variables:
115 NODE_VERSION: '24'
116
117 test:
118 stage: test
119 image: node:${NODE_VERSION}
120 script:
121 - npm ci
122 - npm test
123
124 publish:
125 stage: publish
126 image: node:${NODE_VERSION}
127 id_tokens:
128 NPM_ID_TOKEN:
129 aud: "npm:registry.npmjs.org"
130 SIGSTORE_ID_TOKEN:
131 aud: sigstore
132 script:
133 - npm ci
134 - npm run build --if-present
135 - npm publish
136 only:
137 - tags
138 ```
139
140 The `id_tokens` configuration tells GitLab to generate an OIDC token for npm. Learn more in [GitLab's OIDC documentation](https://docs.gitlab.com/ee/ci/cloud_services/).
141
142 <Note>
143
144 **Note:** Don't forget to configure id_tokens 'aud' to `"npm:registry.npmjs.org"` in your GitLab pipeline.
145
146 </Note>
147
148 ### Managing trusted publisher configurations
149
150 You can modify or remove your trusted publisher configuration at any time through your package settings on [npmjs.com](https://npmjs.com) → Packages → YOUR_PACKAGE → Settings → Trusted publishing. Each package can only have one trusted publisher connection at a time, but this connection can be edited or deleted as needed. To change providers (for example, switching from GitHub Actions to GitLab CI/CD), simply edit your existing configuration and select the new provider. The change takes effect immediately for future publishes. To remove trusted publishing entirely and return to token-based authentication, delete the trusted publisher configuration from your package settings.
151
152 ## Recommended: Restrict token access when using trusted publishers
153
154 Once you've configured trusted publishers for your package, we strongly recommend restricting traditional token-based publishing access for enhanced security.
155
156 ### How to configure maximum security
157
158 1. After enabling trusted publishers, navigate to your package's **Settings** → **Publishing access**
159 2. Select **"Require two-factor authentication and disallow tokens"**
160 3. Save your changes by clicking on **Update Package Settings**
161
162 ### Why this matters
163
164 Trusted publishers use short-lived, scoped credentials that are generated on-demand during your CI/CD workflow, eliminating the need for long-lived tokens. By restricting traditional token access while using trusted publishers, you reduce potential security risks associated with credential management.
165
166 **Note:** The "disallow tokens" setting only affects traditional token authentication. Your trusted publishers will continue to work normally, as they use OIDC tokens.
167
168 ### Migration tip
169
170 If you're transitioning from token-based publishing:
171
172 1. Set up trusted publishers first and verify they work
173 2. Then restrict token access as described above
174 3. [Revoke any existing automation tokens](https://docs.npmjs.com/revoking-access-tokens) that are no longer needed
175
176 This ensures a smooth transition without disrupting your release process.
177
178 ## Automatic provenance generation
179
180 When you publish using trusted publishing, npm automatically generates and publishes [provenance attestations](./generating-provenance-statements) for your package. This happens by default—you don't need to add the `--provenance` flag to your publish command.
181
182 <Screenshot src="/packages-and-modules/securing-your-code/trusted-publisher-provenance.png" alt="Screenshot showing provenance badge/information on a package page" />
183
184 Provenance provides cryptographic proof of where and how your package was built, allowing users to verify its authenticity. This automatic generation only applies when all of these conditions are met:
185
186 - Publishing via trusted publishing (OIDC)
187 - Publishing from a public repository
188 - Publishing a public package
189
190 <Note>
191
192 **Note:** Provenance generation is [not supported for private repositories](https://github.blog/changelog/2023-07-25-publishing-with-npm-provenance-from-private-source-repositories-is-no-longer-supported/), even when publishing public packages.
193
194 </Note>
195
196 ### Disabling provenance generation
197
198 While we strongly recommend keeping provenance enabled, you can disable it if needed. Set the `provenance` option to `false` in any of these ways:
199
200 **Using environment variable:**
201
202 ```bash
203 NPM_CONFIG_PROVENANCE=false npm publish
204 ```
205
206 **In your `.npmrc` file:**
207
208 ```ini
209 provenance=false
210 ```
211
212 **In your `package.json`:**
213
214 ```json
215 {
216 "publishConfig": {
217 "provenance": false
218 }
219 }
220 ```
221
222 ## Security best practices
223
224 ### Prefer trusted publishing over tokens
225
226 When trusted publishing is available for your workflow, always prefer it over long-lived tokens. Traditional npm tokens pose several security risks:
227
228 - They can be accidentally exposed in CI logs or configuration files
229 - They require manual rotation and management
230 - If compromised, they provide persistent access until revoked
231 - They often have broader permissions than necessary
232
233 Trusted publishing eliminates these risks by using short-lived, workflow-specific credentials that are automatically managed and cannot be extracted.
234
235 ### Handling private dependencies
236
237 While trusted publishing handles the publish operation, you may still need authentication for installing private npm dependencies. For this scenario, we recommend:
238
239 ```yaml
240 # GitHub Actions example
241 - uses: actions/setup-node@v4
242 with:
243 node-version: '24'
244 registry-url: 'https://registry.npmjs.org'
245 # Use a read-only token for installing dependencies
246 - run: npm ci
247 env:
248 NODE_AUTH_TOKEN: ${{ secrets.NPM_READ_TOKEN }}
249
250 # Publish uses OIDC - no token needed
251 - run: npm publish
252 ```
253
254 Always use [read-only granular access tokens](/creating-and-viewing-access-tokens#creating-granular-access-tokens-on-the-website) for installing dependencies. This limits potential damage if the token is ever compromised.
255
256 ### Additional security measures
257
258 Consider implementing these additional security practices:
259
260 - Use [deployment environments](https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment) to add approval requirements
261 - Enable [tag protection rules](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/managing-repository-settings/configuring-tag-protection-rules) to control who can create release tags
262 - Regularly audit your trusted publisher configurations
263 - Remove any unused publish tokens from your npm account
264
265 ## Troubleshooting
266
267 If you encounter an "Unable to authenticate" error when publishing, first verify that the workflow filename matches exactly what you configured on [npmjs.com](https://npmjs.com), including the `.yml` extension. All fields are case-sensitive and must be exact. Also ensure you're using GitHub-hosted runners or GitLab.com shared runners, as self-hosted runners are not currently supported. For GitHub Actions specifically, check that the `id-token: write` permission is set in your workflow.
268
269 <Note>
270
271 **Note:** npm does not verify your trusted publisher configuration when you save it. Double-check that your repository, workflow filename, and other details are correct, as errors will only appear when you attempt to publish.
272
273 </Note>
274
275 If your package has private dependencies and `npm install` or `npm ci` is failing with authentication errors, remember that trusted publishing only applies to the `npm publish` command. You'll still need to provide a read-only token for installing private packages as shown in the examples above.
276
277 For packages in private repositories, provenance will not be generated even though you're using trusted publishing. This is a [known limitation](https://github.blog/changelog/2023-07-25-publishing-with-npm-provenance-from-private-source-repositories-is-no-longer-supported/) that applies regardless of whether your package itself is public or private.
278
279 Some GitHub Actions workflows use `workflow_call` to invoke other workflows that run `npm publish`, or use `workflow_dispatch` for manual publishing. When this happens, validation checks the calling workflow's name instead of the workflow that actually contains the publish command, which can cause configuration mismatches.
280
281 ## Limitations and future improvements
282
283 Trusted publishing currently supports only cloud-hosted runners. Support for self-hosted runners is intended for a future release. Each package can only have one trusted publisher configured at a time, though you can update this configuration as needed.
284
285 OIDC authentication is currently limited to the publish operation. Other npm commands such as `install`, `view`, or `access` still require traditional authentication methods. The `npm whoami` command will not reflect OIDC authentication status since the authentication occurs only during the publish operation.
286
287 We intend to expand trusted publishing support to additional CI/CD providers and enhance the feature based on community feedback.
288
289 ## Learn more
290
291 - [About npm provenance](./generating-provenance-statements)
292 - [OpenSSF Trusted Publishers specification](https://repos.openssf.org/trusted-publishers-for-all-package-repositories)
293 - [GitHub Actions OIDC documentation](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect)
294 - [GitLab CI/CD OIDC documentation](https://docs.gitlab.com/ee/ci/cloud_services/)
295 - [API documentation for exchanging OIDC ID token for npm registry token](https://api-docs.npmjs.com/#tag/registry.npmjs.org/operation/exchangeOidcToken)