CVE-2026-10796 - nvm mirror version command injection
nvm versions through 0.40.4 can execute shell commands derived from version
strings returned by a configured Node.js or io.js mirror. The dangerous path is
not an application runtime import; it is a developer, CI, container, or agent
workspace that runs nvm install or another version-resolving nvm command
against a mirror outside the default HTTPS Node.js distribution host.
This recipe treats nvm as supply-chain bootstrap code. The patch is to update nvm, but the PR also needs to remove untrusted mirror configuration and reduce the blast radius of installs that run with repository, package, cloud, or deployment credentials.
When to use it
- A repository installs, vendors, curls, sources, or documents nvm in CI, Dockerfiles, devcontainers, Codespaces, self-hosted runners, shell profiles, release scripts, or agent workspaces.
- Workflows run
nvm install,nvm use --install, or wrappers that resolve Node.js/io.js versions from mirrors. NVM_NODEJS_ORG_MIRRORorNVM_IOJS_ORG_MIRRORmay point at private, mutable, internal, untrusted, or non-HTTPS mirrors.- You need a bounded PR or triage note that upgrades nvm and separates Node.js bootstrap from secret-bearing release/deploy jobs.
Inputs
- Dockerfiles, devcontainers, CI workflows, runner setup scripts, shell
profiles, install scripts, release jobs,
.nvmrc, mirror config, generated dependency reports, SBOMs, and docs. - Resolved nvm versions, mirror ownership, HTTPS/immutability policy, adjacent secret names, runner cache ownership, token rotation policy, and bootstrap job boundaries.
- Available shell/script tests, workflow lint, image builds,
nvm --versionchecks, dependency install checks, SBOM, and security scans.
Affected versions
- Vulnerable tool:
nvm <=0.40.4 - Fixed tool:
nvm 0.40.5+ - Affected commands:
nvm installand other commands that resolve a version from a Node.js or io.js mirror index - Affected configuration:
NVM_NODEJS_ORG_MIRRORorNVM_IOJS_ORG_MIRRORpointing at an untrusted, mutable, or non-HTTPS mirror - Not exposed by default: the default
https://nodejs.orgmirror over TLS
Indicator-of-exposure
- The repository installs, vendors, curls, pins, or sources nvm
<=0.40.4in CI, Dockerfiles, devcontainers, bootstrap scripts, shell profiles, Codespaces setup, self-hosted runner images, or agent workspaces. - A controlled workflow runs
nvm install,nvm use --install, or wrapper scripts that resolve Node.js versions from the network. NVM_NODEJS_ORG_MIRRORorNVM_IOJS_ORG_MIRRORis configured to a private mirror, proxy, artifact cache, internal host, orhttp://URL.- The nvm install step runs with
GITHUB_TOKEN, package publish tokens, npm tokens, Git credentials, deploy keys, cloud credentials, SSH keys, model provider keys, or other secrets in the environment. - Build agents fetch dependencies from unreviewed forks or pull requests while also using custom nvm mirrors.
Quick checks:
rg -n "nvm|install\\.sh|NVM_NODEJS_ORG_MIRROR|NVM_IOJS_ORG_MIRROR|nvm install|nvm use --install|\\.nvmrc|node_mirror|iojs_mirror" .
rg -n "GITHUB_TOKEN|GH_TOKEN|NPM_TOKEN|NODE_AUTH_TOKEN|ACTIONS_ID_TOKEN|AWS_|AZURE_|GCP_|SSH_|DEPLOY|MODEL_|OPENAI_|ANTHROPIC_" .github Dockerfile* docker-compose*.yml devcontainer* scripts . 2>/dev/null
nvm --version
Windows:
rg -n "nvm|install\.sh|NVM_NODEJS_ORG_MIRROR|NVM_IOJS_ORG_MIRROR|nvm install|nvm use --install|\.nvmrc|node_mirror|iojs_mirror" .
rg -n "GITHUB_TOKEN|GH_TOKEN|NPM_TOKEN|NODE_AUTH_TOKEN|ACTIONS_ID_TOKEN|AWS_|AZURE_|GCP_|SSH_|DEPLOY|MODEL_|OPENAI_|ANTHROPIC_" .github Dockerfile* docker-compose*.yml devcontainer* scripts .
nvm --version
Do not run a malicious mirror, alter local PATH to fake network tools, print
tokens, or capture live authorization headers during triage.
Remediation strategy
- Upgrade every repository-controlled nvm installation to
0.40.5+. - Replace curl-piped installer snippets and image bootstrap scripts with a pinned release, verified checksum, or package manager source that resolves to the fixed version.
- Remove untrusted or non-HTTPS
NVM_NODEJS_ORG_MIRRORandNVM_IOJS_ORG_MIRRORsettings. If a private mirror is required, require HTTPS, controlled publishing, immutable index content, and owner review. - Split Node.js installation from secret-bearing release, deploy, package publish, and provenance jobs where practical.
- Add a preflight guard that fails before
nvm installif the detected nvm version is below0.40.5or if a mirror URL ishttp://. - If the update cannot land immediately, disable custom mirrors or run nvm only in a tokenless environment until the fixed tool is installed.
- Rotate long-lived tokens that were present when vulnerable nvm commands ran against an untrusted or non-HTTPS mirror.
The prompt
You are remediating CVE-2026-10796 / GHSA-3c52-35h2-gfmm, an nvm command
injection issue caused by trusting version strings from configured Node.js or
io.js mirrors. Produce exactly one output:
- A reviewer-ready PR/change request that upgrades every repository-controlled
nvm installation, removes unsafe mirror configuration, adds safe preflight
checks, refreshes generated artifacts, and documents token cleanup, or
- TRIAGE.md if this repository does not own any affected nvm installation,
custom mirror configuration, CI image, runner bootstrap, or setup script.
## Rules
- Scope only CVE-2026-10796 / GHSA-3c52-35h2-gfmm and directly related nvm
bootstrap, mirror, CI, container, and agent-workspace controls.
- Treat GitHub tokens, npm tokens, package-registry credentials, cloud
credentials, deploy keys, SSH keys, model-provider keys, environment
variables, private mirror URLs, and release artifacts as sensitive.
- Do not reproduce the command injection, run malicious mirrors, fake curl or
wget with exploit content, capture authorization headers, print secrets, or
execute untrusted shell snippets.
- Do not remove Node.js version management without replacing it with an
equivalent controlled install path.
- Do not broaden token scopes or move secrets into earlier bootstrap jobs.
- Do not auto-merge.
## Steps
1. Inventory every nvm reference controlled by this repository: Dockerfiles,
devcontainers, GitHub Actions workflows, CI templates, self-hosted runner
scripts, agent setup scripts, shell profiles, install scripts, release
scripts, `.nvmrc`, generated dependency reports, SBOMs, and docs.
2. Determine every resolved nvm version. A target is vulnerable if it resolves
to `0.40.4` or earlier.
3. Search for `NVM_NODEJS_ORG_MIRROR`, `NVM_IOJS_ORG_MIRROR`, custom mirror
variables, internal artifact-cache hosts, `http://` mirror URLs, and wrapper
scripts around `nvm install` or `nvm use --install`.
4. Search affected install environments for secret names only:
`GITHUB_TOKEN`, `GH_TOKEN`, `NPM_TOKEN`, `NODE_AUTH_TOKEN`, cloud
credentials, SSH keys, deploy keys, package publish tokens, and
model-provider keys. Never print values.
5. If the repository only contains `.nvmrc` and no controlled nvm installer,
image, workflow, or mirror configuration, stop with `TRIAGE.md` listing the
checked files and any external runner owner.
6. Upgrade all controlled nvm installers or vendored copies to `0.40.5+`.
Refresh checksums, image layers, generated setup docs, SBOMs, dependency
reports, and runner metadata.
7. Remove or harden mirror configuration:
- prefer the default HTTPS Node.js mirror;
- reject `http://` mirror URLs;
- require private mirrors to be owned, immutable, HTTPS-only, and reviewed;
- document the team that owns the mirror content.
8. Add safe preflight coverage where practical:
- parse `nvm --version` before any version-resolving command;
- fail closed below `0.40.5`;
- fail closed on non-HTTPS mirrors;
- run before secret-bearing release, deploy, or package-publish steps.
9. Reduce blast radius:
- perform Node.js bootstrap in tokenless jobs where possible;
- separate dependency installation from release publishing;
- avoid custom mirrors for untrusted pull-request workflows;
- clear persisted nvm caches from shared runner images if mirror content was
not trusted.
10. Add a PR body section named `CVE-2026-10796 operator actions` that states:
- nvm versions before and after;
- where nvm is installed or sourced;
- whether custom mirrors were present and who owns them;
- which token-bearing environments were adjacent by secret name only;
- whether token rotation, runner cache cleanup, or mirror audit is needed;
- which validation commands passed.
11. Run relevant validation: shellcheck or script tests, workflow lint, image
build, `nvm --version` checks in refreshed images, dependency install using
the approved mirror, SBOM refresh, and dependency/security scans.
12. Use PR title:
`fix(sec): remediate CVE-2026-10796 in nvm setup`.
## Stop conditions
- No repository-controlled nvm installer, vendored copy, workflow, runner
image, or custom mirror configuration exists.
- nvm is supplied only by an external base image or platform owner; document
the owner and required fixed version.
- The fixed nvm release cannot be consumed without a broader runner or image
migration.
- Verification would require exploit mirror content, live secret-bearing
network capture, or printing credentials.
- Validation fails for unrelated pre-existing reasons; document those failures
instead of broadening scope.
Verification - what the reviewer looks for
- No controlled nvm installer, vendored copy, runner image, Dockerfile,
devcontainer, setup script, or CI bootstrap resolves below
0.40.5. NVM_NODEJS_ORG_MIRRORandNVM_IOJS_ORG_MIRRORare absent, HTTPS-only, or explicitly owned and reviewed.- Affected workflows fail closed before
nvm installif nvm is too old or the mirror is unsafe. - Secret-bearing release and deploy jobs do not run vulnerable nvm bootstrap against untrusted mirror content.
- PR notes cover token rotation and runner-cache cleanup when exposure was plausible.
Output contract
- Reviewer-ready PR upgrading all controlled nvm installers or vendored copies
to
0.40.5+and refreshing checksums, images, setup docs, SBOMs, and reports. - Mirror policy that removes unsafe custom mirrors or requires HTTPS,
immutability, owner review, and fail-closed preflight checks before
nvmresolves versions. - Reduced bootstrap blast radius by moving Node.js install away from secret-bearing release/deploy/package-publish/provenance jobs where practical.
TRIAGE.mdwhen nvm is supplied only by an external base image, platform runner, or setup owner.
Watch for
- Treating
.nvmrcas the vulnerability while missing the actual nvm installer in a base image, bootstrap script, or shared runner. - Updating local docs but leaving CI images pinned to an old
install.shcommit. - Allowing private mirrors over HTTP because they are “internal.”
- Running nvm in the same step that receives package publish, deploy, or cloud credentials.
- Validating with proof-of-concept mirror content instead of safe version and configuration checks.
Related recipes
- CVE-2025-48384 Git submodule config quoting code execution
- CVE-2026-11417 aws-cdk-lib NodejsFunction bundling command injection
- Source code supply-chain build integrity audit
References
- nvm advisory: https://github.com/nvm-sh/nvm/security/advisories/GHSA-3c52-35h2-gfmm
- NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-10796
- Patch commit: https://github.com/nvm-sh/nvm/commit/6d870d182cd5333647ffa16c0d7dbcd817ec27a8
- Patch commit: https://github.com/nvm-sh/nvm/commit/90bb88748ba6c29c2cec73b18ed7057413aef308
- Patch commit: https://github.com/nvm-sh/nvm/commit/70fb4ede6b9731d75d86451d48caa5faffbec21c