Skip to content

Conversation

@ravi-pplx
Copy link

Fixes static authentication token caching issue where tokens from .npmrc were read once during module extension evaluation and cached, causing 401 errors when short-lived credentials expired (e.g., AWS CodeArtifact 12-hour tokens).

Changes:

  • Add _read_npmrc_auth() function to read .npmrc files dynamically on each download instead of caching tokens statically
  • Add _get_auth_from_url() helper to extract auth for specific registry URLs
  • Add npmrc and use_home_npmrc attributes to npm_import_rule
  • Modify _download_and_extract_archive() to read auth dynamically first, with fallback to static auth attributes for backward compatibility
  • Pass npmrc/use_home_npmrc from npm_translate_lock extension instead of static npm_auth* attributes

Changes are visible to end-users: no

Test plan

  • Add unit tests for _get_auth_from_url() helper function
  • Add e2e integration test that verifies tokens are read dynamically:
    • Fetches succeed with valid tokens
    • Fetches fail with 401 when tokens are broken (proving fresh reads)
    • Fetches succeed when tokens are restored
  • Test uses --repository_cache= to force fresh downloads

Fixes: #2547

Fixes static authentication token caching issue where tokens from .npmrc
were read once during module extension evaluation and cached, causing
401 errors when short-lived credentials expired (e.g., AWS CodeArtifact
12-hour tokens).

Changes:
- Add _read_npmrc_auth() function to read .npmrc files dynamically on
  each download instead of caching tokens statically
- Add _get_auth_from_url() helper to extract auth for specific registry URLs
- Add npmrc and use_home_npmrc attributes to npm_import_rule
- Modify _download_and_extract_archive() to read auth dynamically first,
  with fallback to static auth attributes for backward compatibility
- Pass npmrc/use_home_npmrc from npm_translate_lock extension instead
  of static npm_auth* attributes

Testing:
- Add unit tests for _get_auth_from_url() helper function
- Add e2e integration test that verifies tokens are read dynamically:
  * Fetches succeed with valid tokens
  * Fetches fail with 401 when tokens are broken (proving fresh reads)
  * Fetches succeed when tokens are restored
- Test uses --repository_cache= to force fresh downloads

Fixes: aspect-build#2547
@CLAassistant
Copy link

CLAassistant commented Dec 4, 2025

CLA assistant check
All committers have signed the CLA.

@aspect-workflows
Copy link

aspect-workflows bot commented Dec 4, 2025

Bazel 7 (Test)

All tests were cache hits

299 tests (100.0%) were fully cached saving 39s.


Bazel 8 (Test)

All tests were cache hits

262 tests (100.0%) were fully cached saving 37s.


Bazel 7 (Test)

e2e/bzlmod

All tests were cache hits

5 tests (100.0%) were fully cached saving 559ms.


Bazel 7 (Test)

e2e/git_dep_metadata

All tests were cache hits

1 test (100.0%) was fully cached saving 31ms.


Bazel 7 (Test)

e2e/gyp_no_install_script

All tests were cache hits

2 tests (100.0%) were fully cached saving 153ms.


Bazel 7 (Test)

e2e/js_image_oci

All tests were cache hits

1 test (100.0%) was fully cached saving 6s.


Bazel 7 (Test)

e2e/npm_link_package

All tests were cache hits

2 tests (100.0%) were fully cached saving 206ms.


Bazel 7 (Test)

e2e/npm_link_package-esm

All tests were cache hits

2 tests (100.0%) were fully cached saving 224ms.


Bazel 7 (Test)

e2e/npm_link_package-rerooted

All tests were cache hits

2 tests (100.0%) were fully cached saving 199ms.


Bazel 7 (Test)

e2e/npm_translate_lock

All tests were cache hits

3 tests (100.0%) were fully cached saving 681ms.


Bazel 7 (Test)

e2e/npm_translate_lock_disable_hooks

All tests were cache hits

3 tests (100.0%) were fully cached saving 257ms.


Bazel 7 (Test)

e2e/npm_translate_lock_empty

All tests were cache hits

2 tests (100.0%) were fully cached saving 180ms.


Bazel 7 (Test)

e2e/npm_translate_lock_exclude_package_contents

All tests were cache hits

1 test (100.0%) was fully cached saving 34ms.


Bazel 7 (Test)

e2e/npm_translate_lock_link_workspace

All tests were cache hits

2 tests (100.0%) were fully cached saving 225ms.


Bazel 7 (Test)

e2e/npm_translate_lock_multi

All tests were cache hits

2 tests (100.0%) were fully cached saving 164ms.


Bazel 7 (Test)

e2e/npm_translate_lock_partial_clone

All tests were cache hits

1 test (100.0%) was fully cached saving 61ms.


Bazel 7 (Test)

e2e/npm_translate_lock_replace_packages

All tests were cache hits

4 tests (100.0%) were fully cached saving 487ms.


Bazel 7 (Test)

e2e/npm_translate_lock_subdir_patch

All tests were cache hits

1 test (100.0%) was fully cached saving 95ms.


Bazel 7 (Test)

e2e/npm_translate_package_lock

All tests were cache hits

1 test (100.0%) was fully cached saving 31ms.


Bazel 7 (Test)

e2e/npm_translate_yarn_lock

All tests were cache hits

1 test (100.0%) was fully cached saving 31ms.


Bazel 7 (Test)

e2e/package_json_module

All tests were cache hits

1 test (100.0%) was fully cached saving 324ms.


Bazel 7 (Test)

e2e/patch_from_repo

All tests were cache hits

1 test (100.0%) was fully cached saving 31ms.


Bazel 7 (Test)

e2e/pnpm_lockfiles

All tests were cache hits

82 tests (100.0%) were fully cached saving 8s.


Bazel 7 (Test)

e2e/pnpm_repo_install

All tests were cache hits

1 test (100.0%) was fully cached saving 963ms.


Bazel 7 (Test)

e2e/pnpm_version

All tests were cache hits

1 test (100.0%) was fully cached saving 75ms.


Bazel 7 (Test)

e2e/pnpm_workspace

All tests were cache hits

15 tests (100.0%) were fully cached saving 3s.


Bazel 7 (Test)

e2e/pnpm_workspace_deps

All tests were cache hits

3 tests (100.0%) were fully cached saving 428ms.


Bazel 7 (Test)

e2e/pnpm_workspace_rerooted

All tests were cache hits

15 tests (100.0%) were fully cached saving 3s.


Bazel 7 (Test)

e2e/repo_mapping

All tests were cache hits

3 tests (100.0%) were fully cached saving 394ms.


Bazel 7 (Test)

e2e/runfiles

All tests were cache hits

1 test (100.0%) was fully cached saving 110ms.


Bazel 7 (Test)

e2e/stamped_package_json

All tests were cache hits

1 test (100.0%) was fully cached saving 44ms.


Bazel 7 (Test)

e2e/vendored_node

All tests were cache hits

1 test (100.0%) was fully cached saving 70ms.


Bazel 7 (Test)

e2e/vendored_tarfile

All tests were cache hits

1 test (100.0%) was fully cached saving 31ms.


Bazel 7 (Test)

e2e/verify_patches

All tests were cache hits

2 tests (100.0%) were fully cached saving 109ms.


Bazel 7 (Test)

e2e/worker

All tests were cache hits

1 test (100.0%) was fully cached saving 35ms.


Bazel 7 (Test)

e2e/workspace

All tests were cache hits

1 test (100.0%) was fully cached saving 35ms.


Buildifier      Format

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

generate_bzl_library_targets = kwargs.pop("generate_bzl_library_targets", None)
extract_full_archive = kwargs.pop("extract_full_archive", None)
if len(kwargs):
msg = "Invalid npm_import parameter '{}'".format(kwargs.keys()[0])
fail(msg)

P1 Badge Allow npm_import macro to accept npmrc/use_home_npmrc

Although the repository rule now declares npmrc and use_home_npmrc, the npm_import macro still pops only generate_bzl_library_targets/extract_full_archive and fails on any remaining kwargs, so callers cannot pass the new auth-related parameters and the repository rule never sees them (dynamic .npmrc auth remains disabled and passing npmrc will raise "Invalid npm_import parameter"). The macro should accept and forward the new attributes to npm_import_rule.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +518 to +522
def _get_auth_from_url(url, npm_auth_dict):
for registry, auth_info in npm_auth_dict.items():
if registry in url:
if "bearer" in auth_info:
return {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Prefer registry-specific auth over first .npmrc entry

The new _get_auth_from_url helper returns the first registry entry whose key is a substring of the URL, so a global _authToken entry (key "") in ~/.npmrc will always match and short‑circuit even when a scoped registry token is present. In that common setup, downloads for scoped registries will use the global token and get 401s instead of the registry‑specific credentials, which regresses the longest‑prefix selection previously used when static auth was passed to the rule. Consider skipping the empty registry until no specific match exists or applying the same longest‑match logic as _select_npm_auth.

Useful? React with 👍 / 👎.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems correct and an easy test+fix?

@jbedard jbedard requested review from alexeagle and jbedard December 4, 2025 00:22
@ravi-pplx ravi-pplx force-pushed the fix-dynamic-npmrc-auth-v2 branch from 6042fa5 to f0f606e Compare December 4, 2025 06:08
@jbedard
Copy link
Member

jbedard commented Dec 4, 2025

Don't we need to change npm_translate_lock to actually pass this info through to each npm_import?

@jbedard
Copy link
Member

jbedard commented Dec 4, 2025

I think your e2e test needs to be added to CI still?

npm_auth_basic = "",
npm_auth_username = "",
npm_auth_password = "",
npmrc = None,
Copy link
Member

@jbedard jbedard Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see these being specified anywhere?

@jbedard
Copy link
Member

jbedard commented Dec 4, 2025

I'm also curious if #2554 solves this? Can you try that?

That is for 3.x atm though since I think that won't work with bazel6

@ravi-pplx
Copy link
Author

I'm also curious if #2554 solves this? Can you try that?

That is for 3.x atm though since I think that won't work with bazel6

thanks for the review @jbedard. let me test with this change and get back to you

@alexeagle alexeagle removed their request for review December 7, 2025 20:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: use_home_npmrc caches auth tokens statically, causing 401 errors when tokens expire

3 participants