Updating Node.js safely: distro packages, NodeSource, nvm, containers

Updated November 2026

To patch Node.js, stay on an LTS line, update the binary from the same source you installed it from, restart every Node process, and rebuild container images. The last upstream security release was on October 21, 2026: you need at least 22.23.4, 24.22.1 or 26.12.1.

Supported release lines

The Node.js project says production apps should run only Active LTS or Maintenance LTS releases. An LTS line typically gets critical fixes for 30 months in total.

Node.js release lines as of November 3, 2026
LineStatusEnd of lifeMinimum fixed (Oct 21)Latest
26 (Lithium)Active LTS; maintenance from Oct 20, 2027Apr 30, 202926.12.126.13.0
24 (Krypton)Maintenance LTSApr 30, 202824.22.124.22.2
22 (Jod)Maintenance LTSApr 30, 202722.23.422.23.4

Node.js 20 and 25 are end of life; their last releases were 20.20.2 and 25.9.0. Node.js 27 is in its new Alpha phase and is not for production. Starting with 27, every major line becomes LTS after six months as Current. The project notes that end-of-life versions are always affected when a security release comes out.

The October 21 release fixed ten CVEs, four rated High, including a Brotli decoder out-of-bounds write (CVE-2026-111497) and TLS hostname-check bypasses. Check our vulnerability pages for per-CVE details.

Check what you run

A server can have several Node.js installs: a distro package, NodeSource, nvm under a user's home, and copies inside containers. Check the one your service actually starts.

node -v
node -p 'process.version + " " + (process.release.lts || "not LTS")'
which -a node                              # every node on PATH
readlink -f "$(command -v node)"
dpkg -S "$(readlink -f "$(command -v node)")"   # Debian/Ubuntu: which package
rpm -qf "$(readlink -f "$(command -v node)")"   # RHEL/Fedora
ps -eo pid,lstart,cmd | grep '[n]ode'
systemctl cat myapp.service | grep ExecStart

The lstart column shows when each process started. A path under ~/.nvm/versions/ means nvm; /usr/bin/node from a package called nodejs means distro or NodeSource (apt policy nodejs or dnf info nodejs shows which repository). See Check installed versions.

Distro packages

Debian and Ubuntu package older Node.js lines and backport fixes. Debian 13 (trixie) ships Node.js 20 and Debian 12 (bookworm) ships Node.js 18, both past upstream end of life. On November 3, 2026, the Debian tracker still listed most of the October 2026 Node.js CVEs as unfixed in bookworm and trixie, and Ubuntu listed CVE-2026-105482 as "needs evaluation" for all releases. Apply what exists:

sudo apt update && sudo apt install --only-upgrade nodejs    # Debian/Ubuntu
dnf module list nodejs                                        # RHEL 8/9: available streams
sudo dnf upgrade --refresh nodejs                             # RHEL/Fedora

For an internet-facing app, a distro Node.js that lags upstream fixes is a real gap. Moving the app to an upstream LTS build (NodeSource, nvm, or an official container image) closes it faster.

NodeSource packages

NodeSource publishes one repository per major line (for example node_24.x), as .deb and .rpm packages named nodejs. On November 3 its Debian repositories offered 22.23.4, 24.22.2 and 26.13.0. Inside your line, a normal package update is enough:

sudo apt update && sudo apt install --only-upgrade nodejs    # Debian/Ubuntu
sudo dnf upgrade --refresh nodejs                             # RHEL/Fedora/Amazon Linux
node -v

To move to another major line, run that line's setup script. It removes the old NodeSource repository file and adds the new one. Read a script before you run it as root.

curl -fsSL https://deb.nodesource.com/setup_26.x -o nodesource_setup.sh
less nodesource_setup.sh
sudo -E bash nodesource_setup.sh
sudo apt install -y nodejs
# RPM systems: curl -fsSL https://rpm.nodesource.com/setup_26.x -o nodesource_setup.sh
#              sudo bash nodesource_setup.sh && sudo dnf upgrade nodejs

Test your app on the new major line before switching production. Native add-ons usually need npm rebuild or a fresh npm ci.

nvm

nvm installs Node.js per user, under ~/.nvm, with no root needed. Run these as the user that owns the app:

nvm ls                                              # installed versions
nvm install --reinstall-packages-from=current 24    # newest 24.x, copy global packages
nvm alias default 24
nvm uninstall 24.22.0                               # remove the old patch release
nvm install --reinstall-packages-from=current 'lts/*'   # or jump to the newest LTS

Each version lives in its own directory, such as ~/.nvm/versions/node/v24.22.2/bin/node. If a systemd unit or cron job points to the old path, it keeps running the old version; update the path, then restart.

Containers

The official node images were refreshed on October 28, 2026 (26.13.0, 24.22.2 and 22.23.4). Tags exist per line and codename: 26/lithium, 24/krypton, 22/jod, each with -slim, -alpine, -bookworm and -trixie variants. The lts, current and latest tags now all point to 26, so an image built on node:lts just jumped a major version. Pin the major line, for example FROM node:24-trixie-slim, and rebuild:

docker build --pull -t myapp:latest .
docker compose build --pull && docker compose up -d     # recreates containers
docker compose exec app node -v

Alpine's own nodejs package is 24.22.1-r1 in Alpine 3.23 and 3.24 and 22.23.4-r0 in 3.21 and 3.22. See Containers.

Audit npm dependencies

Most Node.js advisories hit packages, not the runtime. In each app directory:

npm audit --omit=dev           # report production dependencies only
npm audit fix                  # apply fixes inside your semver ranges
npm audit signatures           # verify registry signatures and provenance
npm ci                         # clean install from package-lock.json

npm audit exits non-zero when it finds vulnerabilities, so you can fail a CI build on it; --audit-level=high sets the threshold. npm audit fix --force may install SemVer-major versions, so review and test its changes first. Commit the updated package-lock.json and deploy with npm ci.

Restart Node processes

A running process keeps the old binary in memory until it restarts.

sudo systemctl restart myapp.service      # restarts the app
systemctl show -p ExecMainStartTimestamp myapp.service
pm2 update                                # restart the PM2 daemon on the new binary
pm2 reload all                            # zero-downtime reload in cluster mode
pm2 unstartup                             # after a Node.js upgrade; run the command it prints
pm2 startup                               # run the command it prints
pm2 save                                  # save the process list for reboots

PM2's documentation says to regenerate the startup script after every Node.js upgrade, which matters most with nvm because the path changes. Finally, confirm with ps -eo pid,lstart,cmd | grep '[n]ode' that no process started before the update. More in Restarts and reboots.

On an end-of-life line

If you run Node.js 20 or older, or 25, plan a move to 24 or 26. Upgrade dependencies first, run your tests on the new line, then switch with one of the methods above. Commercial support past Maintenance LTS is available through OpenJS Ecosystem Sustainability Program partners. See Is my OS supported?.

Sources