[rush] Add provideNpmrcCredentialsViaEnvironment experiment to restore ${VAR} credentials with PNPM >= 10.34.2 - #5995
Open
Ian Clanton-Thuon (iclanton) with Copilot wants to merge 2 commits into
Open
[rush] Add provideNpmrcCredentialsViaEnvironment experiment to restore ${VAR} credentials with PNPM >= 10.34.2#5995Ian Clanton-Thuon (iclanton) with Copilot wants to merge 2 commits into
provideNpmrcCredentialsViaEnvironment experiment to restore ${VAR} credentials with PNPM >= 10.34.2#5995Ian Clanton-Thuon (iclanton) with Copilot wants to merge 2 commits into
Conversation
…npm 10.34.2+ ignoring ${VAR} in project .npmrc credentials
Co-authored-by: iclanton <5010588+iclanton@users.noreply.github.com>
Member
|
Copilot - I've left comments. |
…ronment Co-authored-by: iclanton <5010588+iclanton@users.noreply.github.com>
Ian Clanton-Thuon (iclanton)
marked this pull request as ready for review
August 28, 2026 07:57
Ian Clanton-Thuon (iclanton)
enabled auto-merge (squash)
August 28, 2026 08:03
provideNpmrcCredentialsViaEnvironment experiment to restore ${VAR} credentials with PNPM >= 10.34.2provideNpmrcCredentialsViaEnvironment experiment to restore ${VAR} credentials with PNPM >= 10.34.2
Contributor
|
I asked Copilot to review your PR. I will take a look when it's done. I do recommend you to do the same on your other PRs as its reviews were mostly legit to me :) |
Contributor
There was a problem hiding this comment.
Pull request overview
Adds an opt-in PNPM workaround that moves environment-expanded .npmrc credentials into npm_config_* variables.
Changes:
- Classifies and transforms sensitive
.npmrcsettings. - Injects reconstructed credentials into PNPM invocation environments.
- Adds experiment configuration, documentation, tests, and change metadata.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
libraries/rush-lib/src/utilities/test/npmrcUtilities.test.ts |
Tests .npmrc transformations. |
libraries/rush-lib/src/utilities/npmrcUtilities.ts |
Implements classification, expansion, markers, and reconstruction. |
libraries/rush-lib/src/schemas/experiments.schema.json |
Defines the experiment schema. |
libraries/rush-lib/src/logic/installManager/WorkspaceInstallManager.ts |
Supplies the subspace .npmrc location. |
libraries/rush-lib/src/logic/installManager/InstallHelpers.ts |
Gates the experiment and prepares PNPM environments. |
libraries/rush-lib/src/logic/base/BaseInstallManager.ts |
Enables credential extraction during .npmrc synchronization. |
libraries/rush-lib/src/logic/Autoinstaller.ts |
Applies credentials to autoinstaller commands. |
libraries/rush-lib/src/cli/RushPnpmCommandLineParser.ts |
Applies credentials to rush-pnpm. |
libraries/rush-lib/src/api/ExperimentsConfiguration.ts |
Exposes the experiment API. |
libraries/rush-lib/assets/rush-init/common/config/rush/experiments.json |
Documents the experiment in generated repositories. |
common/reviews/api/rush-lib.api.md |
Updates the API report. |
common/changes/@microsoft/rush/copilot-npmrc-credentials-experiment_2026-08-28-05-19.json |
Records the Rush minor change. |
Suppressed comments (1)
libraries/rush-lib/src/logic/installManager/InstallHelpers.ts:423
- This object is still
process.envby reference because_mergeEnvironmentVariables()returns itsbaseEnvargument directly. The subsequentObject.assigntherefore permanently installs each subspace's credentials into the Rush process; later subspace installs inherit stale registry credentials that are absent from their own.npmrc. Cloneprocess.envbefore merging so credentials remain scoped to the child invocation.
const packageManagerEnvironment: NodeJS.ProcessEnv = _mergeEnvironmentVariables(
process.env,
configurationEnvironment,
options
);
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
495
to
498
| const packageManagerEnv: NodeJS.ProcessEnv = InstallHelpers.getPackageManagerEnvironment( | ||
| this.rushConfiguration, | ||
| this.options | ||
| { ...this.options, npmrcFolder: subspace.getSubspaceTempFolderPath() } | ||
| ); |
| rushConfiguration: RushConfiguration, | ||
| options: { | ||
| debug?: boolean; | ||
| npmrcFolder?: string; |
Comment on lines
+680
to
+682
| export function getNpmrcEnvironmentVariables( | ||
| options: IGetNpmrcEnvironmentVariablesOptions | ||
| ): Record<string, string> | undefined { |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PNPM 10.34.2 added
dropUntrustedEnvExpansions, which silently discards any auth setting or request destination containing a${VAR}token when it comes from a project or workspace.npmrc. Rush generatescommon/temp/.npmrc, which PNPM loads as both layers, so the documented practice of supplying private-feed credentials via environment variables in CI now fails with a pair ofWARN Ignored project-level auth setting ...messages per credential and unauthenticated requests.Only the
cli,env(npm_config_*), anduserconfig sources are still trusted by PNPM, so this change has Rush do the expansion itself and hand credentials to PNPM throughnpm_config_*variables.Behavior (PNPM only, when the experiment is enabled)
syncNpmrcclassifies each line containing a${VAR}token the same way PNPM does:_authToken,_auth,_password,username,tokenHelper,cert,key— bare or registry-scoped) are replaced with a; PROVIDED VIA ENVIRONMENT:marker that retains the unexpanded original line, and the value is passed vianpm_config_*. The secret never touches disk, and rotating a token doesn't change the file (socleanInstallAfterNpmrcChangesdoesn't spuriously trigger).registry,@scope:registry,proxy,http-proxy,https-proxy, and//...key names) are expanded literally into the generated file — they aren't secret, and the generated file isn't committed.Given
common/config/rush/.npmrc:the generated
common/temp/.npmrcbecomes:and PNPM is invoked with
npm_config_//pkgs.dev.azure.com/.../npm/registry/:_authTokenset to the resolved token.Changes
npmrcUtilities.ts— sensitive-setting classification mirroring PNPM's own lists; consolidated${VAR}expansion into_expandEnvironmentVariables(); newmoveSensitiveSettingsToEnvironmentoption onsyncNpmrc/trimNpmrcFileLines; newgetNpmrcEnvironmentVariables()that reconstructs thenpm_config_*map by re-reading the marker lines.provideNpmrcCredentialsViaEnvironmentinIExperimentsJson,experiments.schema.json, therush inittemplate, and the API report.InstallHelpers.shouldProvideNpmrcCredentialsViaEnvironment()is the single read point and also gates onisPnpm.BaseInstallManagerpasses the new sync option;WorkspaceInstallManagerandAutoinstallerinject the variables into the package manager's environment;rush-pnpmrecomputes them from the already-generated file so it stays authenticated without re-syncing.Notes for reviewers
syncNpmrcruns duringprepareAsyncwhile the install happens later, andrush-pnpmnever syncs at all. Recomputing from the marker comments rather than threading state through keeps all consumers uniform.envKeyToSetting()splits annpm_config_*name at its first colon and normalizes the remainder, so//registry.example.com:8080/:_authTokenwould be mangled into:-authtoken. Such settings fall back to literal expansion in the generated file rather than the environment.npm_config_//...name could in principle be altered. Unverified, and part of why this is behind an experiment.SetupPackageRegistry,rush publish(.npmrc-publish), andinstall-run.jsare unchanged — the option defaults tofalse.Verified against pnpm 10.34.5 (warning gone,
Authorizationheader sent) and pnpm 9.15.9 (unchanged behavior) using a local registry; the sandbox's network restrictions prevented a fullrush install.