Previously the message read "No .nvmrc file found",
which obscured the fact that the user also did not pass a version.
The new wording names both halves of the actual problem.
Refs #3755
Currently these commands silently fall back to the active node version when neither a version argument nor an `.nvmrc` resolves,
making them invisibly dependent on shell state and impossible to script predictably (see #3755).
Print a stderr deprecation warning in this case (suppressed by `--silent`) and continue with the active node version,
so existing callers keep working.
The follow-up change will turn this into a hard error;
pass `current` explicitly (e.g. `nvm exec current node ...`) to silence the warning and lock in the new behavior now.
Refs #3755
The branch-reset step sent `force` as a string via `gh api -f "force=true"`,
which the Git refs API rejects ("not a boolean", HTTP 422), failing the release run.
Use `-F` so it is sent as a boolean.
Also resolve the version from the latest `vX.Y.Z` tag
(via the tags API) rather than `releases/latest`,
so a manual `workflow_dispatch` with no input works even before the GitHub release object for a freshly pushed tag is published.
Upstream's `.gitmodules` uses a relative submodule url (`../nvmrc.git`),
which resolves against the superproject's origin:
on a fork without its own `nvmrc` fork that is `<owner>/nvmrc`,
which 404s and fails `actions/checkout` with `submodules: true`.
Keep `submodules: true` (so a fork's own `nvmrc` is used when present),
but mark checkout `continue-on-error` and, only when it failed,
re-point the submodule at `nvm-sh/nvmrc` and update.
The mirror-supplied (untrusted) version flows into download URLs,
filesystem paths, and the checksum awk match.
Reject any version outside the node/io.js grammar
(`[0-9A-Za-z._+-]`) before it is used.
A blocklist of metacharacters is used rather than a strict semver allowlist so RCs, nightlies, v8-canary, and io.js versions still install.
Completes the remediation of GHSA-3c52-35h2-gfmm.
The awk program string-interpolated the slug
(which embeds the untrusted, mirror-supplied version)
into its source, so a crafted version such as
`v1"==$2){system("touch${IFS}/tmp/x")}#`
was executed by awk's `system()`.
Pass the value via `-v tarball=...` so awk treats it as data and never as code.
See GHSA-3c52-35h2-gfmm
(a second injection sink fed by the same untrusted version field that `nvm_download`'s eval was; the source-install path reaches this during a normal `nvm install <version>`).
`nvm_download` built a curl/wget command string and ran it with `eval`.
The download URLs embed the version string taken from the mirror's `index.tab`,
which is untrusted.
Wrapping each argument in double quotes inside the `eval` does not prevent command substitution,
so a version field such as `v1$(touch /tmp/proof)` was executed by the shell.
This bypassed the earlier quoting hardening in 0ce8f5a.
Pass every argument as a literal argv element instead of constructing a string for `eval`,
on both the curl and wget paths,
so URL arguments are never re-parsed by the shell.
The wget flag translation is now done per-argument with a POSIX
`set --` loop rather than `sed` over the joined string.
The auth header is sanitized and added once,
before invoking the downloader.
The wget path passed `NVM_AUTH_HEADER` as the raw header line
(e.g. `--header "Bearer secret-token"`),
omitting the `Authorization:` header name that the curl path includes.
Per the documented usage
(`NVM_AUTH_HEADER="Bearer secret-token"`) the value is the credential,
so wget was sending a malformed header.
Prefix it with `Authorization: ` to match the curl path.
The test's `rm -rf "$NVM_DIR"` intermittently failed with
`rm: cannot remove...: Directory not empty`
and aborted under `set -e`.
Cause: after the clone/fetch, git can spawn a detached background gc/maintenance process that keeps writing into the clone dir while `rm -rf` runs (a concurrent writer makes the final rmdir fail).
It is not egress- or version-related
(it reproduces with all endpoints allowed),
and it is environment-timing dependent
(recently became consistent on the GitHub runners).
Disable git's background work for the test (gc.autoDetach / maintenance.auto)
so all git operations finish synchronously, and retry the rm once as a safety net.
`[ "${head_ref}" != "${avoid_ref}"]` is missing the space before the closing bracket,
so the shell prints `[: missing ']'` and the avoid_ref assertion never actually runs
(it is inside an `if` condition, so the error was non-fatal and silently disabled the check)
CodeQL (actions/missing-workflow-permissions)
flagged the matrix, test, and finisher jobs of nvm-install-test.yml for not declaring permissions.
Every other test workflow already sets least-privilege permissions per job; add them here to match:
`contents: read` for the matrix and test jobs, `contents: none` for the no-op finisher.
harden-runner runs with `egress-policy: block`, and the allow-list only included
`production.cloudflare.docker.com`. DockerHub serves image blobs from either its
Cloudflare or its CloudFront CDN; when a pull was routed to CloudFront
(`production.cloudfront.docker.com`) the connection was dropped, causing
`error pulling image configuration: ... connect: connection refused` and exit
125 in the xenial, installation_node, and fast (httpbin) suites. Allow both CDNs.
Container-based suites and the `nvm_download` httpbin check hard-fail whenever DockerHub is briefly unreachable
(observed: `dial tcp ...:443: connect: connection refused` while pulling images),
even though the change under test is fine.
This is unrelated to any test logic.
- tests-xenial / tests-installation-node: retry the `docker pull` up to 5 times before `docker run`, mirroring the existing apt-get retry
- `nvm_download` test: retry the httpbin pull and skip the auth-header checks (rather than fail) when the image cannot be pulled or run, and make cleanup tolerant of a missing container.
GNU Tar has `--preserve-permissions` as a default enabled when executed as the superuser (root).
This will cause the binaries to be installed using the permissions (owner and group) as defined in the tarball.
The argument `--no-same-owner` prevents this and will install the binaries as the effective owner/group just like when nvm is executed as a non superuser.
Updated the install from binary test from the installation_node test
suite because this test is run in a docker container as root. Without
--no-same-owner this test will fail beause the binaries of node v0.10.7
are owned by isaacs/admin in the tarball.
The lowercase check was in the `*` catch-all branch of the `case` statement, rejecting any alias name with uppercase characters.
This prevented creating or reading uppercase aliases like `TESTY`.
The check should only apply to `lts/*` patterns, since LTS codenames are always lowercase.
Fixes#3764.
Bug introduced in 9fb9dec710 as part of fixing #3417.
- `nvm-exec` test: expect "Found .nvmrc" message in output, since `nvm_rc_version` now outputs it to stdout via fd 3 redirection (ef162036)
- `nvm_install_binary_nosource`: fix exit code capture by running the command directly instead of inside a subshell with `echo $?` (05d78477)
- `nvm_iojs_version_has_solaris_binary`: bare versions like `v3.3.1` (without `iojs-` prefix) are node versions and should be rejected. The old tests relied on the buggy comparison that let them through (53e6244a)
- `nvm_get_arch_unofficial`: copy `uname` into the chroot. The old test passed only because the unconditional `NVM_ARCH=x64-musl` masked the missing binary, but the `case` fix now requires a real arch to match (39e71eab)
If directory creation fails (e.g., permissions), the script would continue and fail with confusing errors later.
Fail early with a clear error message instead.
Bugs introduced in 68bf93514b, 6cee20a071, and 703babe60a.
- Use `=` instead of `==` for string comparison (POSIX compliance)
- Use `printf '%b'` instead of variable as format string (prevents `%` characters in paths from being interpreted as format specifiers)
- Fix `TRIED_PROFILE` to reference `PROFILE` instead of `NVM_PROFILE` which is known to be empty at that point
Bugs introduced in a24ff3e605, b6f1c156da, and a461a0fffc (PR https://github.com/nvm-sh/nvm/pull/1605).
`${2}` was empty because positional parameters had been consumed by `shift` in the argument parsing loop.
Use `${provided_version}` which holds the resolved alias name.
Bug introduced in 1c00753fd9.
The `*` glob was inside double quotes, preventing shell expansion. `nvm_grep -l` received a literal `*` filename instead of the list of alias files, so aliases pointing to uninstalled versions were never cleaned up.
Bug introduced in 7807a9f09e.
Missing `_` prefix on the right side of the comparison meant the guard clause that rejects non-iojs versions almost never matched, allowing non-iojs versions to fall through.
Bug introduced in 2d692d9d78 / #854.
`return` inside `(...)` subshells only exits the subshell, not the calling function.
Errors in mkdir, download, and checksum verification were silently ignored.
Use `{ ...; }` brace groups instead.
Bug introduced in ba3ad8e460.
When `nosource=1` (the `-b` flag) and binary download fails, the function returned 0 (success) instead of a non-zero exit code, masking the installation failure.
Bug introduced in 4fdef427e4 / #2439.
Alpine detection unconditionally set `x64-musl` regardless of actual architecture, which would be incorrect on ARM-based Alpine containers.
Bug introduced in ef7fc2f2c0 / #3212.
Fixes#3616.
Other `uname` calls in the file use `command uname` to bypass any user aliases or functions.
This one was missing it.
Bug introduced in 779a34e6a9 / #2469.
Using a variable as the format string means `%` characters in alias names would be interpreted as format specifiers.
Use `%b` format with the variable as an argument to safely interpret `\n` escapes.
Bug introduced in 9b91734f0b.
The awk expression `$0 ~ "regex"` as a bare statement in the action block evaluates the match but doesn't affect the exit code.
awk always prints the line and exits 0, making the validation a no-op.
Bug introduced in b1fa143dd8.
`return $A || $B` only evaluates the first argument, since `return` always succeeds.
The io.js exit code was never checked, silently swallowing remote listing failures.
Bug introduced in ea12784629 / #616.
The error message for using `-s` and `-b` together was calling
`nvm err` (invoking nvm with subcommand "err") instead of the
`nvm_err` helper function, causing the error message to never be displayed and instead showing the help text with exit code 127.
Bug introduced in 4fdef427e4 / #2439
Colors were lost because `nvm_has_colors` checks `[ -t 1 ]`, which is false inside the `(...) | sort` pipeline in `nvm_list_aliases`.
Evaluate `nvm_has_colors` before the pipe and propagate via `NVM_HAS_COLORS`, matching the approach used by `nvm_print_versions`.
Bug introduced in 35212c1346.