Patching Dependencies

Keeping Node and Its Dependencies Patched

Patching is a schedule, not a project. Node.js 2,131 ships security releases on announced dates for every supported line at once, so the runtime is the easy half: stay on Active LTS and rebuild your images when one lands. On 17 September 2026 that is Node.js 24.21.0 "Krypton" (Active LTS, maintenance from 20 October 2026, end of life 30 April 2028), with 22.23.2 "Jod" in maintenance until 30 April 2027 and 26.9.0 Current, becoming LTS on 28 October 2026. Node.js 20 and 25 are end of life and receive no security fixes.

The dependency half needs automation, because nobody reads 300 changelogs. Renovate 22,612 (https://github.com/renovatebot/renovate 22,612 ) (AGPL-3.0) is configurable and self-hosts; Dependabot 29 is built into GitHub 29 with no setup. Both open pull requests carrying the changelog and the diff, grouped to keep review cheap:

.github/dependabot.yml — weekly grouped updatesYAML
version: 2
updates:
  - package-ecosystem: npm
    directory: /
    schedule: { interval: weekly }
    groups:
      minor-and-patch:
        update-types: [minor, patch]

Whatever opens the pull request, the gate is the lockfile. npm 2,036 ci installs exactly what package-lock.json records and verifies every tarball against the integrity hash beside it. Change one byte of that hash and the install stops (digests elided to fit the page):

Output of 131
npm error code EINTEGRITY
npm error sha512-AAAA...AAAA== integrity checksum failed when using sha512:
npm error wanted sha512-AAAA...AAAA== but got sha512-r34yH/G...yakl1vg==. (146732 bytes)

That catches a tampered mirror or a corrupted cache, not a maintainer who published malicious code under a legitimate hash. For that, npm audit signatures checks registry signatures and provenance attestations across the tree; on a small pino-based project it reports "14 packages have verified registry signatures" and "2 packages have verified attestations". A package that carried an attestation and stopped deserves a look.

The routine fits in one CI job: npm ci, npm audit --audit-level=high --omit=dev, npm audit signatures. Pin the runtime the way you pin packages — "engines": { "node": ">=24.21.0 <25" }, a pinned node:24-alpine digest, a committed .nvmrc — because drifting onto an end-of-life line is the failure nobody notices.