Skip to content
Latchkey

npm "403 Forbidden" on Install - Fix Blocked Registry Reads in CI

A 403 on install (not publish) means the registry authenticated the request but refused the read. The token is valid, but policy - a blocked package, an entitlement, or a proxy rule - forbids fetching it.

What this error means

npm install/npm ci fails with E403 403 Forbidden - GET for a package, even though authentication succeeds for other packages. It is a permission/policy refusal, not a missing package (404) or bad auth (401).

npm output
npm error code E403
npm error 403 Forbidden - GET https://registry.internal/@acme%2fpkg
npm error Package "@acme/pkg" is blocked by policy / not entitled for this token.

Diagnose it: which registry, and with what credentials?

Registry errors are resolved in a precedence chain, and the effective value is rarely the one in the file you are looking at. Scoped registries, .npmrc files at several levels, and environment variables all combine before a request is made.

Terminal
# the effective, fully merged configuration
npm config list -l | grep -E "registry|_auth|always-auth"

# where each value came from
npm config get registry
npm config get @yourscope:registry

# prove the token works, independently of the install
curl -sI -H "Authorization: Bearer $NPM_TOKEN" \
  "$(npm config get registry)@yourscope%2fpackage" | head -1

Common causes

The token lacks entitlement to read the package

On a private/proxy registry, a token may authenticate but not be entitled to a particular scope or package, so reads return 403.

A proxy or security policy blocks the package

A pull-through proxy with an allowlist/denylist (or a vulnerability policy) can forbid specific packages or versions with a 403.

How to fix it

Use a token entitled for the scope

Authenticate with a token that has read access to the package’s scope on the right registry.

Terminal
npm config get registry
# ensure the scope maps to the entitled registry and token:
cat .npmrc
# @acme:registry=https://registry.internal
# //registry.internal/:_authToken=${NPM_TOKEN}

Check proxy/policy rules

  1. Confirm the package/version is allowed by the proxy’s policy.
  2. Verify the token’s entitlements cover the scope being read.
  3. If a vulnerability policy blocks a version, pin to an allowed one.

How to prevent it

  • Grant CI tokens read entitlement for every scope they install.
  • Keep proxy allowlists in sync with your dependency set.
  • Pin to versions your security policy permits.

Frequently asked questions

What causes npm "403 Forbidden" on install?
There are 2 common causes: the token lacks entitlement to read the package and a proxy or security policy blocks the package. On a private/proxy registry, a token may authenticate but not be entitled to a particular scope or package, so reads return 403.
How do I fix npm "403 Forbidden" on install?
There are 2 fixes depending on which cause you have: use a token entitled for the scope and check proxy/policy rules. Work through them in order, since the first is the most common.
What does npm "403 Forbidden" on install actually mean?
npm install/npm ci fails with E403 403 Forbidden - GET for a package, even though authentication succeeds for other packages.
How do I stop npm "403 Forbidden" on install happening again?
Grant CI tokens read entitlement for every scope they install. The prevention section lists 3 changes that keep it from recurring.

Related guides

References

This is a registry failure, not a bug in your code. Latchkey detects, repairs, and retries it for you. Start free → 30-day trial · No credit card