claude-code icon indicating copy to clipboard operation
claude-code copied to clipboard

[BUG] Claude Code Proxy Issue: Private NPM Package Authentication Failure

Open ejkani opened this issue 1 month ago • 3 comments

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Claude Code Proxy Issue: Private NPM Package Authentication Failure

Date: 2025-11-05 Environment: Claude Code on the Web Issue: Cannot authenticate with GitHub Packages npm registry for private packages Status: Blocking development workflow

The Claude Code proxy's scoped credential system successfully injects GitHub authentication for git operations but does not provide the necessary read:packages scope for accessing private npm packages from GitHub Packages registry. Additionally, when users attempt to provide their own authentication token via .npmrc, the proxy strips the Authorization header, preventing any workaround.

Impact: Users cannot install private npm packages from GitHub Packages, blocking dependency installation for projects that rely on private organizational packages.

What Should Happen?

Executive Summary

The Claude Code proxy's scoped credential system successfully injects GitHub authentication for git operations but does not provide the necessary read:packages scope for accessing private npm packages from GitHub Packages registry. Additionally, when users attempt to provide their own authentication token via .npmrc, the proxy strips the Authorization header, preventing any workaround.

Impact: Users cannot install private npm packages from GitHub Packages, blocking dependency installation for projects that rely on private organizational packages.


Technical Details

Environment

  • Platform: Claude Code on the Web
  • Proxy: Claude Code HTTPS security proxy (as documented)
  • Registry: npm.pkg.github.com (GitHub Packages npm registry)
  • Package Type: Private scoped npm packages (@organization/package-name)
  • Authentication Method Attempted: Personal Access Token (classic) with read:packages scope

The Problem

Claude Code's proxy implements a scoped credential system that automatically injects GitHub authentication for *.github.com domains. However:

  1. The injected credential lacks read:packages scope needed for GitHub Packages npm registry
  2. User-provided authentication tokens are stripped by the proxy
  3. No documented workaround exists for private package registry authentication

Error Messages/Logs


Steps to Reproduce

Reproduction Steps

Setup

  1. Create a private npm package published to GitHub Packages:

    • Organization: <your-org>
    • Package: @<your-org>/<package-name>
    • Version: 1.0.0-<hash>
    • Published to: https://npm.pkg.github.com/<your-org>
  2. Create repository with read access:

    • Repository: <your-org>/<your-repo>
    • Grant repository read access to the package in GitHub Packages settings
  3. Create Personal Access Token (classic):

    • Scope: read:packages
    • Verify it works locally on developer machine

Test Case 1: Using .npmrc with Authentication Token

Configuration:

# .npmrc in project root
registry=https://npm.pkg.github.com/<your-org>
//npm.pkg.github.com/:_authToken=ghp_[40-character-token]

Command:

npm install @<your-org>/<package-name>@<version>

Expected Result: Package installs successfully (this works on local machine with identical configuration)

Actual Result:

npm error code E401
npm error Unable to authenticate, your authentication token seems to be invalid.

Evidence:

17 http fetch GET 401 https://npm.pkg.github.com/<your-org>/@<your-org>%2f<package-name> 26ms (cache skip)
23 verbose stack HttpErrorAuthUnknown: Unable to authenticate, need: Bearer realm="", error="invalid_token"

Analysis:

  • Error code 401 Unauthorized means no authentication was received by GitHub
  • The same .npmrc and token work perfectly on local machine
  • Verbose curl output shows proxy strips the Authorization header:
    * [HTTP/2] [1] [authorization: token ]
    
    (Header is empty - token was stripped)

Test Case 2: Relying on Proxy Auto-Injected Credentials

Configuration:

# .npmrc without authentication token
registry=https://npm.pkg.github.com/<your-org>

Command:

npm install @<your-org>/<package-name>@<version>

Expected Result: Proxy injects GitHub authentication with sufficient scope to access packages

Actual Result:

npm error code E403
npm error 403 403 Forbidden - GET https://npm.pkg.github.com/<your-org>/@<your-org>%2f<package-name>
npm error 403 Permission denied

Analysis:

  • Error code 403 Forbidden (not 401) proves authentication IS being sent
  • The proxy successfully injects its scoped credential
  • But the credential lacks the read:packages scope needed for private packages
  • This matches the documented behavior: "scoped credential" works for git, but not for package registries

Test Case 3: Direct curl Access

Command:

curl -H "Authorization: Bearer $GITHUB_TOKEN" \
  "https://npm.pkg.github.com/@<your-org>/<package-name>"

Result:

{"error":"unauthenticated: User cannot be authenticated with the token provided."}

Analysis:

  • Same 401 error as npm
  • Confirms the proxy strips Authorization headers for npm.pkg.github.com
  • The proxy's scoped credential injection doesn't apply to curl (or doesn't have proper scope)

Evidence Summary

Test Scenario Auth Method HTTP Status Error Message Interpretation
With user token in .npmrc User-provided PAT 401 "invalid_token" Proxy strips auth header
Without auth in .npmrc Proxy-injected 403 "Permission denied" Proxy token lacks read:packages
Same .npmrc on local machine User-provided PAT 200 Success Proves token and config are valid
curl with Bearer token User-provided PAT 401 "unauthenticated" Confirms header stripping

Claude Model

Other

Is this a regression?

I don't know

Last Working Version

No response

Claude Code Version

Claude Code Web

Platform

Other

Operating System

Other

Terminal/Shell

Other

Additional Information

Root Cause Analysis

Based on Claude Code documentation and observed behavior:

From Documentation

"the git client uses a scoped credential inside the sandbox, which the proxy verifies and translates to your actual GitHub authentication token"

This scoped credential system:

  • Works for git operations (clone, fetch, push to current branch)
  • Does not extend to npm registry authentication
  • Lacks read:packages scope even if it did apply

From Observed Behavior

  1. Proxy intercepts all HTTPS traffic to npm.pkg.github.com
  2. Proxy strips user-provided Authorization headers (security feature)
  3. Proxy injects its own scoped credential for GitHub domains
  4. Scoped credential has insufficient permissions for private package access

Business Impact

Affected Use Cases

  1. Private organizational npm packages - Cannot access internal design systems, shared libraries, or proprietary components
  2. Monorepo development - Cannot install workspace dependencies published to GitHub Packages
  3. Enterprise workflows - Organizations using GitHub Packages for internal distribution are blocked
  4. Third-party private packages - Cannot consume private packages from vendors using GitHub Packages

Current Workarounds

Workaround 1: Manual tarball distribution

# Developer downloads locally
npm pack @organization/package@version
# Manually provides .tgz file to Claude Code session
npm install ./package.tgz
  • ❌ Breaks automated workflows
  • ❌ Requires manual intervention for every package update
  • ❌ Not scalable for multiple dependencies

Workaround 2: Make packages public

  • ❌ Not acceptable for proprietary code
  • ❌ Security and compliance concerns
  • ❌ Defeats purpose of private packages

Workaround 3: Use alternative registries

  • ❌ Forces architecture changes
  • ❌ Requires migrating packages
  • ❌ May not be feasible for existing projects

Proposed Solutions

Solution 1: Extend Scoped Credential Scope (Recommended)

Description: Extend the proxy's auto-injected GitHub token to include read:packages scope.

Implementation:

  • When proxy detects requests to npm.pkg.github.com
  • Inject GitHub token with both git and package registry scopes
  • Similar to how git credentials are currently handled

Pros:

  • ✅ Seamless user experience
  • ✅ No configuration required
  • ✅ Consistent with existing git authentication pattern
  • ✅ Works for all GitHub Packages registries (npm, maven, nuget, etc.)

Cons:

  • Requires infrastructure changes to proxy
  • May need user consent for expanded scope

Solution 2: Allow User-Provided Registry Authentication

Description: Configure proxy to preserve Authorization headers for package registry domains.

Implementation:

  • Add npm.pkg.github.com to allowlist for passthrough auth
  • Preserve Authorization headers for recognized package registries
  • Users provide tokens via .npmrc as standard practice

Pros:

  • ✅ Standard npm authentication pattern
  • ✅ Users control token scopes
  • ✅ Works with existing workflows
  • ✅ Supports all package registries (npm, PyPI, etc.)

Cons:

  • May conflict with proxy security model
  • Requires careful allowlist management

Solution 3: Registry-Specific Proxy Translation

Description: Implement credential translation specifically for package registries.

Implementation:

  • Similar to git credential translation
  • Detect package registry requests (npm.pkg.github.com, pypi.org, etc.)
  • Translate user session credentials to appropriate registry auth

Pros:

  • ✅ Maintains proxy security model
  • ✅ Extensible to other registries
  • ✅ User-transparent authentication

Cons:

  • Most complex to implement
  • Requires per-registry integration

Solution 4: Documentation and Configuration Guide

Description: If technical limitation prevents proxy-level fix, provide clear documentation.

Implementation:

  • Document the limitation in Claude Code docs
  • Provide detailed workaround instructions
  • Add troubleshooting section for package registry auth

Pros:

  • ✅ Immediate availability
  • ✅ Sets correct user expectations

Cons:

  • ❌ Doesn't solve the underlying problem
  • ❌ Still blocks workflows

Recommended Action

Priority: High - This blocks a common enterprise development pattern

Suggested Approach:

  1. Short-term: Document the limitation and workarounds (Solution 4)
  2. Medium-term: Implement Solution 2 (passthrough auth for registries)
  3. Long-term: Implement Solution 1 (extend scoped credentials)

Additional Context

Related Documentation

  • Claude Code Network Access: https://docs.claude.com/en/docs/claude-code/claude-code-on-the-web#network-access-and-security
  • Scoped Credential System: Mentioned in proxy documentation

Related Issues

  • Similar to how the proxy handles git authentication successfully
  • May affect other package managers (pip, cargo, maven, nuget) accessing private registries
  • GitHub issue reference: Users report .npmrc setup before claude-code-action as workaround
    • This suggests workflow-level configuration might work
    • But doesn't solve the core proxy authentication issue

Verification Steps for Anthropic Engineering

To reproduce this issue:

  1. Create a private npm package in any GitHub organization
  2. Publish to GitHub Packages npm registry
  3. Create a repository and grant it package read access
  4. In Claude Code session:
    • Create .npmrc with proper authentication
    • Attempt npm install @org/package@version
    • Observe 401 error
  5. Remove authentication from .npmrc:
    • Keep only registry=https://npm.pkg.github.com/org
    • Attempt npm install again
    • Observe 403 error (proving auth is injected but lacks scope)
  6. Test same configuration locally:
    • Use identical .npmrc with authentication
    • Observe successful installation

This demonstrates:

  • User token + config are valid (works locally)
  • Proxy strips user auth (401 with token, 403 without)
  • Proxy injects credential (403 vs 401) but insufficient scope

Date: 2025-11-05

This issue is blocking active development and would benefit from Anthropic engineering review.

ejkani avatar Nov 05 '25 21:11 ejkani

I'm running into this a lot... I've managed to work around almost every other CCW issue, but this one is beyond my ability to work around.

sethb75 avatar Nov 18 '25 07:11 sethb75

This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.

github-actions[bot] avatar Dec 18 '25 10:12 github-actions[bot]

Experiencing the same issue and it's a major blocker. Surprisingly, it works with bun install (if executed in the "Full" network mode), but not with yarn or npm, probably since bun doesn't use the http proxy inside the container.

haikov avatar Dec 23 '25 09:12 haikov