Safeguard
Supply Chain Security•

How to Install Node.js and npm on Windows, macOS and Linux Safely

Install Node.js LTS from nodejs.org: nvm on macOS and Linux, the signed MSI or nvm-windows on Windows. Then verify SHASUMS256 and avoid sudo with npm.

Safeguard Security Team
35 min read

Install Node.js only from nodejs.org, and pick the LTS line. On macOS and Linux, the Node.js download page recommends nvm: run the pinned nvm install script, then nvm install 24. On Windows, use the signed .msi installer from nodejs.org, or nvm-windows as Microsoft suggests. npm comes bundled with Node, so node -v and npm -v confirm both.

The rest of this guide covers which version to choose this week (the answer changes on 28 October 2026), how to check a download against the signed SHASUMS256 file, what the nvm script does to your shell, why sudo npm install -g backfires, and how to patch, upgrade and remove Node. Every command comes from nodejs.org, the npm docs, the nvm README or Microsoft Learn.

Key takeaways

  • Download Node.js only from nodejs.org; release files live under https://nodejs.org/dist/.
  • On 23 October 2026 the download page defaults to v24.22.1 LTS. Node.js 26 is scheduled to become LTS on 28 October 2026, and Node.js 22 reaches end of life on 30 April 2027.
  • Version managers are the route both the npm docs and Microsoft recommend for developers. nvm (macOS, Linux, WSL) and nvm-windows (native Windows) install Node into your user account, so global npm installs never need sudo.
  • Verify what you downloaded: check the GPG signature on SHASUMS256.txt.asc with the release keyring, then check the file hash with shasum. On macOS, pkgutil --check-signature also shows the Apple notarization; on Windows, Get-AuthenticodeSignature shows the code signature.
  • Follow the Node.js security releases. The 21 October 2026 release fixed four high severity issues, and end of life versions are "always affected" by each one.

Which Node.js version should you install: LTS or Current?

Install the LTS line unless you have a specific reason not to. The Node.js previous releases page states that "production applications should only use Active LTS or Maintenance LTS releases." Current releases are where library authors test new features; LTS releases are where you run real work.

Under the schedule that applies up to Node.js 26, each major version spends six months as Current. Even numbered versions then move to Active LTS, and odd numbered versions become unsupported. LTS "typically guarantees that critical bugs will be fixed for a total of 30 months", according to the same page.

The release lines on 23 October 2026

These dates come from the Node.js release schedule file and the nodejs.org download and previous releases pages, all fetched on 23 October 2026.

LineCodenameLatest releaseBundled npmStatus todayNext milestoneEnd of life
v26none yetv26.12.111.20.0CurrentBecomes LTS on 28 Oct 202630 Apr 2029
v25nonev25.9.011.12.1End of lifeEnded 1 Jun 20261 Jun 2026
v24Kryptonv24.22.111.19.1Maintenance LTS since 20 Oct 2026Security and critical fixes only30 Apr 2028
v22Jodv22.23.410.9.9Maintenance LTSSecurity and critical fixes only30 Apr 2027
v20Ironv20.20.2n/aEnd of lifeNone30 Apr 2026

For most people this week, that means v24.22.1, the download page default, supported until April 2028. New projects shipping in 2027 should test on v26 now and move once it is promoted on 28 October. On v22 you have about six months; on v20 or older you get no fixes at all.

The new yearly schedule from Node.js 27

In March 2026 the Node.js releasers announced that from 27.x there will be one major release a year, and every release becomes LTS. A new Alpha channel (October to March) replaces odd numbered releases, followed by six months of Current and 30 months of LTS, 36 months in total. The schedule file lists the Node.js 27 Alpha starting on 28 October 2026.

The download page warns that Alpha releases "are not intended for production use." Use them in a CI matrix, never on a production server.

Installer, version manager or package manager: which route should you use?

The Node.js download page lets you choose an operating system, a version and an install method. It also offers prebuilt installers and standalone binaries. Here is what it lists, and what each route means for security and upkeep.

RoutePlatforms on nodejs.orgWho maintains itAdmin rights neededMultiple versionsBest fit
Prebuilt installer (.msi on Windows, .pkg on macOS)Windows, macOSNode.js projectYesNoA single machine that needs one LTS version
Standalone binary (.zip, .tar.xz)Windows, macOS, LinuxNode.js projectNo, if unpacked into your home directoryManualServers, locked down laptops, offline installs
nvmmacOS, Linux, WSL and other POSIX shellsnvm project (community)NoYesDevelopers on macOS, Linux and WSL
nvm-windowsNative Windowsnvm-windows project (community)Installer asks for itYesDevelopers on native Windows, per Microsoft Learn
fnm, n, asdf and other version managersMostly macOS and LinuxTheir own projectsNoYesTeams that already standardise on one
HomebrewmacOS, LinuxHomebrew (community)NoPer major versionMachines already managed with Homebrew
ChocolateyWindowsChocolatey communityYesLimitedWindows fleets already managed with Chocolatey
Docker imageWindows, macOS, LinuxDocker official image maintainersDocker accessYes, per tagRepeatable builds and CI
Distribution package (apt, dnf and others)LinuxYour distributionYesNoOnly when the distribution's version is a supported LTS

nodejs.org marks nvm, fnm and Docker as recommended and labels the rest community options, each with a notice that the tool "and their installation scripts are not maintained by the Node.js project."

The npm documentation is blunt about installers: "We strongly recommend using a Node version manager like nvm to install Node.js and npm. We do not recommend using a Node installer, since the Node installation process installs npm in a directory with local permissions and can cause permissions errors when you run npm packages globally." Microsoft gives the same advice in its Windows and WSL setup guides, because "versions change very quickly" and you will likely need to switch between versions for different projects.

The installer is not unsafe, just a poor fit for developers who need several versions. On macOS it also installs into root owned /usr/local, the usual cause of EACCES errors.

One Microsoft warning applies to every version manager: nvm is "designed to be installed per-user, and invoked per-shell. It is not designed for shared developer boxes or build servers with multiple build agents." On shared build machines, use the standalone binary or a container image instead.

Step by step: install Node.js on Windows

You have three sound choices on Windows: the official MSI, nvm-windows, or Node inside WSL 2. Microsoft's guidance on picking between native Windows and WSL is practical. If you are new to Node or prefer PowerShell, use native Windows. If you prefer Bash or will deploy to Linux servers, use WSL 2, and keep your project files in the same file system where Node is installed.

Option 1: the official MSI installer

  1. Go to nodejs.org and open Download. Pick the LTS version (v24.22.1 on 23 October 2026), Windows, and x64 or ARM64. Current lines no longer offer 32 bit builds.
  2. Download the Windows Installer (.msi). The file will be named like node-v24.22.1-x64.msi.
  3. Before you run it, verify it. The steps are in the verification section below and take under a minute.
  4. Run the installer and accept the defaults unless you have a reason to change them.
  5. Open a new PowerShell window, not one that was already open, and check:
node -v # Should print "v24.22.1".
npm -v # Should print "11.19.1".

Those two commands, with their expected output, come straight from the nodejs.org download page. If PowerShell says node is not recognised, see the common errors section.

Option 2: nvm-windows

The nvm README says nvm does not support native Windows (only WSL, Git Bash or Cygwin). Microsoft Learn recommends nvm-windows instead, with these steps:

  1. Remove any existing Node.js install first. Microsoft is clear that different install types "can lead to strange and confusing conflicts", and that you should delete leftover directories such as C:\Program Files\nodejs, because the nvm symlink "will not overwrite an existing (even empty) installation directory."
  2. Go to the nvm-windows repository on GitHub (github.com/coreybutler/nvm-windows) and open its Releases page. Download nvm-setup.zip for the most recent release. Do not get it from anywhere else.
  3. Open the zip, run nvm-setup.exe, and choose the directories for nvm-windows and Node.js.
  4. Open PowerShell and work through the commands Microsoft lists:
nvm ls
nvm list available
nvm install 24.22.1
nvm use 24.22.1
npm --version

nvm list available shows the current LTS numbers so you can choose one. nvm ls shows what is installed. After nvm use, the npm version changes to whichever npm ships with that Node version.

Option 3: Node.js inside WSL 2

Install WSL from Microsoft's WSL documentation, update the distribution with sudo apt update && sudo apt upgrade, then follow the Linux nvm steps inside WSL. Do not use Ubuntu's apt-get Node, which Microsoft calls "currently outdated."

Note one difference between sources. Microsoft's WSL page shows the nvm install command fetching install.sh from the nvm master branch. The nvm README pins a tagged release in the URL. Use the tagged version, for the reasons in the nvm section below.

Step by step: install Node.js on macOS

Option 1: nvm (recommended on nodejs.org)

  1. Install the Xcode Command Line Tools first if you have not already. The nvm README explains that since OS X 10.9, /usr/bin/git is preset by the Xcode command line tools, so nvm "can't properly detect if Git is installed or not", and the install script will fail without them.
  2. Since macOS 10.15 the default shell is zsh. nvm looks for ~/.zshrc, which does not exist on a fresh Mac. Create it first:
touch ~/.zshrc
  1. Run the install, exactly as the nodejs.org download page shows it for LTS:
# Download and install nvm:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.8/install.sh | bash

# in lieu of restarting the shell
\. "$HOME/.nvm/nvm.sh"

# Download and install Node.js:
nvm install 24

# Verify the Node.js version:
node -v # Should print "v24.22.1".

# Verify npm version:
npm -v # Should print "11.19.1".
  1. Confirm nvm itself loaded:
command -v nvm

It should print nvm. The README notes that which nvm will not work, "since nvm is a sourced shell function, not an executable binary."

On Apple silicon, the nvm README notes that Node started offering arm64 Darwin packages from v16.0.0. Any supported LTS line today has native arm64 builds.

Option 2: the official .pkg installer

  1. On the download page, choose LTS and macOS, then download the macOS Installer (.pkg), named like node-v24.22.1.pkg.
  2. Verify it (see the verification section). On a Mac this includes a signature and notarization check.
  3. Run the installer. It installs Node and npm under /usr/local, which is why global npm installs afterwards hit permission errors unless you change npm's prefix.

When we expanded the v24.22.1 pkg on 23 October 2026, it contained two component packages with the identifiers org.nodejs.node.pkg and org.nodejs.npm.pkg, installing into /usr/local/bin, /usr/local/include/node and related paths, and requiring root authorisation. Those identifiers matter when you uninstall.

Option 3: Homebrew

If the Mac is already managed with Homebrew, the nodejs.org page shows:

brew install node@24

nodejs.org offers Homebrew only for Current and LTS releases, and the nvm README states plainly that installing nvm itself through Homebrew "is not supported."

Step by step: install Node.js on Linux

Linux has no official installer on nodejs.org; the configuration behind the download page marks Linux as not supporting installers. Your choices are a version manager, the official binary archive, a container image, or your distribution's package.

Option 1: nvm

The commands are the same as macOS. On Ubuntu, Microsoft's WSL guide also installs curl first:

sudo apt-get install curl
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.8/install.sh | bash
\. "$HOME/.nvm/nvm.sh"
nvm install 24
node -v
npm -v

If command -v nvm prints nothing afterwards, the nvm README says to "close your current terminal, open a new terminal, and try verifying again", or reload your shell file with source ~/.bashrc (bash) or source ~/.zshrc (zsh).

The README also accepts nvm install --lts. A number such as 24 is more predictable in scripts, because the LTS alias will mean v26 after 28 October.

Option 2: the official Linux binary archive

The download page offers a Standalone Binary (.tar.xz) for Linux x64, ARM64 and other platforms. For v24.22.1 on x64 that file is node-v24.22.1-linux-x64.tar.xz, and a musl build for Alpine style systems is node-v24.22.1-linux-x64-musl.tar.xz.

Verify it as shown below, then unpack it into a directory you own, such as ~/.local, so node, npm and npx land in ~/.local/bin. The npm docs give this ~/.profile line for that directory:

PATH=~/.local/bin:$PATH

Then reload it:

source ~/.profile

Keeping Node under your home directory means no sudo for Node or for global npm packages. For a shared server, unpack into a system directory owned by root instead, and run updates as an administrator through your normal change process.

Option 3: the official Docker image

nodejs.org lists Docker as a recommended method on all three platforms:

# Pull the Node.js Docker image:
docker pull node:24-slim

# Create a Node.js container and start a Shell session:
docker run -it --rm --entrypoint sh node:24-slim

This is the cleanest option for CI and for keeping the host free of Node altogether. Our guide to running Node.js in Docker covers image tags, non root users and rebuilds.

Option 4: your distribution's package

Distribution packages are patched by your distribution's security team, which helps on servers, but they are often old. Microsoft's WSL guide calls the Ubuntu apt-get version "currently outdated." Run node -v and compare the major version with the release table; if it is v20 or older, do not use it.

How do you verify a Node.js download with SHASUMS256 and GPG?

Every Node.js release directory contains three files that matter:

  • SHASUMS256.txt, a list of SHA-256 hashes for every file in that release.
  • SHASUMS256.txt.asc, the same list clearsigned with the releaser's GPG key.
  • SHASUMS256.txt.sig, a detached signature over SHASUMS256.txt.

The Node.js release process document explains why: "for releases, this file is signed by the individual responsible for that release," so that the public can check it "has been signed by someone who has been authorized to create a release." The hash proves the file matches the list. The signature proves the list came from a Node.js releaser. You need both.

Where the release keys live

The release signing keys are listed in the "Release keys" section of the nodejs/node README and in the nodejs/release-keys repository; on 23 October 2026 both list eight active releasers. The repository offers raw keys in keys/, a keyring with active and retired keys in gpg/, and an active only keyring in gpg-only-active-keys/. Use the full keyring for older releases signed by retired keys.

The release-keys README suggests cross checking that list against nodejs.org before you trust a keyring.

Verify on macOS or Linux

This is the method from the nodejs/node README. First fetch the keyring:

curl -fsLo "/path/to/nodejs-keyring.kbx" "https://github.com/nodejs/release-keys/raw/HEAD/gpg/pubring.kbx"

Then, in the directory holding your download, fetch the signed checksum file for that release, verify its signature, and check the hash of your file:

VERSION=v24.22.1
curl -fsO "https://nodejs.org/dist/${VERSION}/SHASUMS256.txt.asc" \
&& gpgv --keyring="/path/to/nodejs-keyring.kbx" --output SHASUMS256.txt < SHASUMS256.txt.asc \
&& shasum --check SHASUMS256.txt --ignore-missing

We ran this against the v24.22.1 macOS pkg on 23 October 2026. gpgv reported "Good signature" from key 5BE8A3F6C8A5C01D106C0AD820B1A390B168D356, which matches the first active releaser in the README, and shasum printed node-v24.22.1.pkg: OK. Two practical notes from that run. shasum warns that one line is "improperly formatted"; that is the blank line left over from the signature block, not a failure. And with one recent GnuPG build, gpgv left its output in SHASUMS256.txt.part instead of SHASUMS256.txt. If shasum cannot find the file, look for the .part file.

The README also lists a gpg --recv-keys command per fingerprint for importing keys from a public key server, with the caveat that the project "cannot guarantee the availability of the server nor the keys on that server." The bundled keyring is the simpler route.

Verify on Windows

Windows does not ship shasum, but PowerShell's Get-FileHash computes SHA-256 by default:

Get-FileHash .\node-v24.22.1-x64.msi | Format-List

Compare the Hash value with the line for that file in SHASUMS256.txt from the same release directory. For v24.22.1 the expected value for the x64 MSI begins 3bda4baf1ee7. Get-FileHash prints uppercase hex and the file uses lowercase; the value is the same. Comparing a hash only proves the file matches the list, so also verify the list's signature with GnuPG for Windows if you have it, or with WSL using the commands above.

Then check the installer's code signature:

Get-AuthenticodeSignature -FilePath .\node-v24.22.1-x64.msi

Microsoft documents that this cmdlet is only available on Windows, and that when a file is not signed "the information is retrieved, but the fields are blank." You want a Status of Valid and a signer certificate that belongs to the Node.js project's foundation. A blank or NotSigned result on something claiming to be a Node.js installer is a reason to stop.

Verify the code signature on macOS

pkgutil --check-signature node-v24.22.1.pkg

On 23 October 2026 this reported, for the official v24.22.1 pkg, "signed by a developer certificate issued by Apple for distribution", "Notarization: trusted by the Apple notary service", and a certificate named "Developer ID Installer: Node.js Foundation (HX7739G8FX)". If you see a different developer name, or no notarization, delete the file.

What does the nvm install script do, and how do you pin it?

The nvm README describes exactly what happens when you pipe install.sh into bash. The script "clones the nvm repository to ~/.nvm, and attempts to add the source lines" to your profile file, which is one of ~/.bashrc, ~/.bash_profile, ~/.zshrc or ~/.profile. The lines it adds are:

export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm

Other behaviour worth knowing, all from the README:

  • You can control the install source, directory, profile and version with NVM_SOURCE, NVM_DIR, PROFILE and NODE_VERSION.
  • Setting PROFILE=/dev/null stops it editing any shell file at all, for people who manage their dotfiles another way.
  • Running the same script again is also how you update nvm.

For a longer look at the files it touches, see what the nvm install script changes on your machine.

Pin the script to a tag

The official URL contains the tag v0.40.8, so you get the script released as v0.40.8, not whatever is on the default branch that minute. The README says only the latest nvm version "is supported", so bump the tag when nvm releases.

If you would rather not pipe anything into a shell, the README describes two alternatives. "Download and run the script manually" lets you read it first. The git install clones the repository and checks out a tag explicitly:

cd ~/
git clone https://github.com/nvm-sh/nvm.git .nvm
cd ~/.nvm
git checkout v0.40.8
. ./nvm.sh

You then add the loader lines to your shell file yourself. This route makes the pinned tag explicit and leaves you in control of every file change.

How do you avoid lookalike sites and fake Node.js installers?

Searches for "download Node.js" return ads, download portals and repackaged installers. None of them offers anything nodejs.org does not. A few rules keep you safe.

  • Type the address. The official site is nodejs.org, and release files are served from https://nodejs.org/dist/. A "Node.js installer" link on any other domain is not official.
  • Know the official homes of the tools around Node. npm documentation is at docs.npmjs.com. nvm lives at github.com/nvm-sh/nvm. nvm-windows, as Microsoft links it, lives at github.com/coreybutler/nvm-windows. Release keys live at github.com/nodejs/release-keys.
  • Verify every download. A good signature from the release keyring plus a matching hash is the strongest check you have.
  • Treat community installers as separate suppliers. Homebrew, Chocolatey and other package managers can be fine, but nodejs.org says plainly that it does not maintain them. Decide on purpose whether your organisation trusts each one.

After install, every npm install pulls more code. Our guides on checking an npm package before installing it and npm install script security cover that step.

Why you should not use sudo with npm global installs

When Node is installed into a system directory, such as /usr/local, npm's global prefix points there too; the npm folders docs say the prefix "defaults to the location where node is installed."

Your user cannot write to /usr/local/lib/node_modules, so npm install -g fails with EACCES. Do not reach for sudo: it runs install scripts as root and leaves root owned files that cause the next error. The nvm README agrees that with nvm "you do not need sudo."

The npm docs give two fixes.

Fix 1, recommended: reinstall Node with a version manager. The npm docs call this "the best way to avoid permissions issues", and add: "You do not need to remove your current version of npm or Node.js before installing a node version manager." With nvm, every Node version and its global packages live under your home directory.

Fix 2: give npm a user owned prefix. This applies to macOS and Linux only; the docs say it "does not apply to Microsoft Windows." The steps, verbatim from the npm docs:

npm config set prefix ~/.local

Add this line to ~/.profile:

PATH=~/.local/bin:$PATH

If you use zsh (check with echo $0), also add this line to ~/.zprofile:

source ~/.profile

Then update your environment and test with a global install that does not use sudo:

source ~/.profile
npm install -g npm-check-updates
ncu -g

The nvm README has one compatibility warning: if you use nvm, make sure ~/.npmrc "does not contain any prefix settings", because a custom prefix is not compatible with nvm. Pick one approach, not both.

For tools you only run now and then, the npm docs suggest npx as an alternative to global installs, which avoids the global folder entirely.

How do you keep Node.js patched and follow security releases?

Watch the right channels

The Node.js project publishes security releases on a schedule it announces in advance. Each announcement says which lines are affected and the highest severity. The pre-announcement for October 2026 points to the low volume nodejs-sec mailing list for "security vulnerabilities and security-related releases", and to the project's security policy. Subscribe to that list, or follow the vulnerability category of the nodejs.org blog.

The 21 October 2026 security release shows why. It shipped v26.12.1, v24.22.1 and v22.23.4, fixed four high severity issues including two TLS hostname verification bypasses and a Brotli decoder out of bounds write, and updated bundled c-ares, Undici, OpenSSL and the CA certificates after the eMudhra intermediate CA compromise, which our eMudhra explainer covers.

If your Node is older than those versions, update now:

nvm install 24
node -v

With nvm, nvm install 24 fetches the newest 24.x release. For the MSI or pkg, download and verify the new installer and run it over the old one. For Docker, pull the tag again and rebuild your images. Our step by step guide to updating Node.js covers each route in more detail.

End of life lines get every vulnerability and no fixes

The Node.js end of life page puts it plainly: when a line reaches end of life, it "will no longer receive updates, including security patches." Since a 2025 policy change, the project's CVEs include end of life releases in their scope by default, and every security release announcement repeats that "End-of-Life versions are always affected when a security release occurs." The project does not evaluate reports against end of life lines, so assume any new Node.js CVE applies to them.

The same page warns that "many industry audits forbid unmaintained runtimes," and describes paid end of life support as "a temporary solution."

Move between LTS lines without losing your tools

nvm can carry your global packages across when you change lines. To install the newest LTS and copy the global packages from the version you are using now, the README gives:

nvm install --reinstall-packages-from=current 'lts/*'

For versions you already have, nvm reinstall-packages copies global packages into the active one. Either way, the README notes, "the npm version itself is not changed."

Before switching a project, pin the line in the repository. nvm reads a .nvmrc file in the project folder, so nvm use picks the right version, and CI can read the same file. Our guide to the setup-node GitHub Action shows how to make CI use the same version as developers.

Keep npm itself current

npm is bundled with Node, and the npm docs update it with npm install -g npm. With nvm, that applies to the active Node version only.

Corepack after Node.js 25

Corepack, which manages Yarn and pnpm versions, used to ship inside Node. The v24 Corepack docs now say it "will no longer be distributed starting with Node.js v25." It is still in the v24 installers, but on v26 you install it yourself. The nodejs.org download page gives:

npm install -g corepack

If a project's scripts call corepack enable and fail with "command not found" after you move to Node 26, this is why.

How do you uninstall Node.js cleanly?

First, record what you will lose. List your global packages so you can reinstall the ones you need:

npm ls -g
npm prefix -g

npm prefix -g prints the global prefix, which tells you where the global packages actually live.

Uninstalling an nvm managed Node version

nvm uninstall 22

The README also supports LTS aliases, such as nvm uninstall --lts. To remove nvm itself, the README's manual uninstall is:

nvm_dir="${NVM_DIR:-~/.nvm}"
nvm unload
rm -rf "$nvm_dir"

Then edit your shell file (for example ~/.bashrc) and remove the NVM_DIR and loader lines the installer added.

Uninstalling on Windows

Remove Node.js from Settings, Apps, Installed apps. Then follow Microsoft's advice to delete leftover directories such as C:\Program Files\nodejs, which otherwise block nvm-windows later. The npm folders documentation puts the global prefix on Windows at %AppData%\npm, with global packages under its node_modules folder; delete that folder too if you want no trace of global tools. Open a new terminal and confirm node -v no longer runs.

Uninstalling the macOS pkg

The Node.js project does not publish an uninstaller for the pkg. macOS keeps a receipt of every file a pkg installed, and pkgutil (documented in its macOS man page) can read it. The Node pkg uses the receipt identifiers org.nodejs.node.pkg and org.nodejs.npm.pkg:

pkgutil --pkgs=org.nodejs
pkgutil --files org.nodejs.node.pkg
pkgutil --files org.nodejs.npm.pkg

Review the lists (paths are relative to /usr/local) and remove those files. Then clear the receipts; the man page says --forget does "not touch the installed files", so run it last:

sudo pkgutil --forget org.nodejs.node.pkg
sudo pkgutil --forget org.nodejs.npm.pkg

Finally, check /usr/local/lib/node_modules for leftover global packages.

Uninstalling on Linux

If you used a binary archive under ~/.local, delete the Node files from it and remove the PATH line if nothing else uses it. If you used a distribution package, remove it with your package manager. If you used Docker, remove the images.

Common errors and how to fix them

"node is not recognized as an internal or external command"

On Windows this almost always means the terminal was opened before the install changed PATH. Open a new PowerShell window. If you use nvm-windows, run nvm ls and nvm use with an installed version. If it still fails, check for a leftover C:\Program Files\nodejs directory; Microsoft notes that the nvm symlink will not overwrite an existing directory, even an empty one.

EACCES when installing a global package

Your global prefix is in a directory you do not own. Reinstall Node with a version manager, or set a user prefix with npm config set prefix ~/.local, as described above. Do not use sudo npm install -g.

An old Node version from apt

node -v prints a version that is end of life. Microsoft's WSL guide notes the Ubuntu apt-get version is "currently outdated." Remove the distribution package and use nvm, the official binary archive or Docker. If you must use the distribution package on a server, check that its major version is a supported LTS line.

"nvm: command not found" after installing

Close and reopen the terminal. On macOS, create ~/.zshrc if it is missing and rerun the installer, and make sure the Xcode Command Line Tools are installed. If it still fails, add the loader lines from the nvm section to your shell file yourself, as the README suggests.

Corepack missing, or npm and Corepack versions not matching

On Node 25 and later, install Corepack with npm install -g corepack. If npm -v does not match the version listed for your Node release (11.19.1 for v24.22.1), npm was updated separately or a different Node is first on your PATH. Check node -v, command -v node (or where.exe node on Windows) and npm -v together.

Common mistakes

  • Downloading from a portal or an ad. nodejs.org is the only source.
  • Verifying the hash but not the signature. Whoever can swap a file can usually swap the hash beside it; only the signature ties the list to a releaser.
  • Piping an unpinned script into bash. Use the tagged nvm URL, update the tag when nvm releases, and read the script if you can.
  • Using sudo to fix EACCES. It makes the next error worse and runs install scripts as root.
  • Installing Current on a production server. Production should run Active LTS or Maintenance LTS, and from Node.js 27 never an Alpha.
  • Forgetting about end of life. Node 20 reached end of life on 30 April 2026.
  • Updating Node on laptops but not in images and CI. The Node in your Dockerfile and your CI configuration needs the same patch discipline as the one on your desk.

Fix it without waiting for upstream

Installing a patched Node.js runtime is the easy part. The npm dependencies your projects pull in afterwards change far more often, and a vulnerable version can sit in a lockfile for months before anyone notices.

Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.

1. Autonomous remediation: pull requests, not tickets

When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.

2. Gold Open Source: the safe version in seconds, free

gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.

3. Gold Registry: start from components that are already fixed

registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.

When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.

Your situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingThe Gold scan GitHub Action in CI, plus Safeguard policies and gates
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch (early access)
You want to start clean on new projectsPull hardened components and images from Gold Registry

One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.

FAQ

How do I install Node.js on Windows 10 or 11?

Download the LTS .msi from nodejs.org, check it with Get-FileHash and Get-AuthenticodeSignature, install it, and run node -v in a new PowerShell window. For several versions, Microsoft recommends nvm-windows.

How do I install Node.js on a Mac?

Use nvm as nodejs.org recommends: install the Xcode Command Line Tools, create ~/.zshrc if needed, run the pinned nvm install script, then nvm install 24. The signed, notarized .pkg also works but installs into root owned /usr/local.

How do I install Node.js on Ubuntu?

Use nvm or the official binary archive from nodejs.org rather than the default apt package, which Microsoft's WSL guide describes as outdated. With nvm: sudo apt-get install curl, run the pinned install script, reload your shell, then nvm install 24.

Should I install the LTS or Current version of Node.js?

LTS. The Node.js project says production applications should only use Active LTS or Maintenance LTS releases. On 23 October 2026 that means v24, with v26 becoming LTS on 28 October 2026.

How do I install nvm?

On macOS, Linux or WSL, run curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.8/install.sh | bash, open a new terminal, and check with command -v nvm. On native Windows, nvm does not work; use nvm-windows from its GitHub releases page.

How do I check that my Node.js download is genuine?

Download SHASUMS256.txt.asc from the same release folder, verify its GPG signature against the keyring in the nodejs/release-keys repository, and check your file's SHA-256 hash against it with shasum --check. On macOS also run pkgutil --check-signature; on Windows, Get-AuthenticodeSignature.

Is it safe to run sudo npm install -g?

No. It runs package install scripts as root and creates root owned files that cause later errors. Use a version manager, or set a user owned prefix with npm config set prefix ~/.local as the npm docs describe.

How do I update Node.js to the latest LTS?

With nvm, run nvm install --reinstall-packages-from=current 'lts/*' to get the newest LTS and copy your global packages. With an installer, download and verify the new LTS installer and run it over the old one.

See how Safeguard would help

Safeguard does not install Node.js or check whether an installer is genuine; the steps above do that. It helps afterwards, once your projects pull npm dependencies and build images on that runtime. Dependencies in your repositories and the packages inside your container images appear in Safeguard SBOMs, so a vulnerable npm package, or a Node.js runtime in an image that the vulnerability databases flag, shows up as a finding. If you want to try it, download the Safeguard CLI and follow the CLI setup guide.

The first demo is a real CLI session. After install, safeguard opens the interactive terminal, you ask it to fix the lodash CVE in a repo, and it reads the finding and advisory, asks before each command, edits package.json to lodash 4.17.21, runs npm install and npm test with your approval, prints a summary and pushes nothing. On a machine where you have just installed or upgraded Node, the same flow handles the vulnerable packages that arrive with your first npm install.

Click through it at your own pace, or open it full screen.

The second demo sets up the Safeguard runner on your own machine, approves it with its device code, and then scans from the terminal. That is how you get a dependency inventory of the Node projects on a developer laptop or build host without moving the code anywhere else.

Click through it at your own pace, or open it full screen.

The third demo connects Claude to the Safeguard MCP server with OAuth and shows how you choose which Safeguard tools Claude can use. If your team already asks Claude about its Node projects, this is how those answers can draw on your own Safeguard findings rather than guesses.

Click through it at your own pace, or open it full screen.

Quick check

Why do you need both the GPG signature and the SHA-256 hash to verify a Node.js download?

The hash proves your file matches the entry in SHASUMS256.txt. The signature proves that SHASUMS256.txt was signed by an authorised Node.js releaser, using a key listed in the nodejs/release-keys repository. Without the signature, anyone who could swap the file could also swap the hash list.

What are the two fixes the npm docs give for EACCES on global installs?

Reinstall Node with a version manager such as nvm, which the docs call the best way to avoid permission issues, or on macOS and Linux set a user owned prefix with npm config set prefix ~/.local and add ~/.local/bin to PATH. Using sudo is not one of them.

Sources

Last reviewed: 23 October 2026. Node.js release lines change on 28 October 2026 when v26 becomes LTS; check the linked nodejs.org pages for the current versions and security releases.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.