#!/usr/bin/env bash # Install Node.js from NodeSource, then refuse a build whose version is # below the newest security release for that line. NodeSource mirrors can lag # a release, and without this check a stale mirror ships a vulnerable image # that looks like a normal successful build. # usage: install-node.sh set -euo pipefail major="${1:?usage: install-node.sh }" case "$major" in ''|*[!0-9]*) echo "bad Node major: $major" >&2; exit 64;; esac # Minimum acceptable version per line. Raise these when Node.js publishes a # security release. 18 and 20 are end of life and get no fixes upstream. declare -A MIN=( [22]=22.23.4 # 2026-10-20 security release (CVE-2026-111497 Brotli, +9) [24]=24.22.1 [26]=26.12.1 ) # NodeSource repo written by pkg-cache-repos.sh with the signing key committed # in keys/pkg-cache/ (replaces `curl setup_N.x | bash`, an unverified remote # script). With PKG_CACHE (CI, cache reachable) the repo goes through the # internal cache with the origin as 2nd baseurl; the caller's RUN must end with # `pkg-cache-repos.sh restore`. RPMs are GPG-checked either way. /usr/local/sbin/pkg-cache-repos.sh nodesource "$major" dnf install -y nodejs # npm 12 dropped Node 18/20; on those lines keep the npm Node ships with # (what the old per-version scripts did, silently, before this one failed hard). npm install -g npm@latest || echo "WARNING: npm@latest does not support Node $major; keeping bundled npm $(npm --version)" >&2 have="$(node -p 'process.versions.node')" case "$have" in "$major".*) ;; *) echo "ERROR: wanted Node $major, got $have" >&2; exit 1;; esac if [ -n "${MIN[$major]:-}" ]; then if [ "$(printf '%s\n%s\n' "${MIN[$major]}" "$have" | sort -V | head -1)" != "${MIN[$major]}" ]; then echo "ERROR: Node $have is below the security floor ${MIN[$major]} for line $major (mirror behind?)" >&2 exit 1 fi else echo "WARNING: Node $major is end of life; this image gets no Node.js security fixes." >&2 fi echo "node $have, npm $(npm --version)"