Skip to content

chore(docker): bump the Node base image to clear container vulnerabilities - #663

Merged
nicholasjjlim merged 1 commit into
mainfrom
chore/bump-node-base-image
Sep 17, 2026
Merged

nicholasjjlim merged 1 commit into
mainfrom
chore/bump-node-base-image

Conversation

@nicholasjjlim

@nicholasjjlim nicholasjjlim commented Sep 17, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #656

🚀 Summary

  • Bumps the base image to node:24.21.0-alpine3.23, applies the outstanding Alpine security updates, and deletes the Node parts that no published stage runs.
  • All 87 Inspector findings on pr-662-latest (5 critical, 44 high, 29 medium, 9 low) come from the base image. Not one sits under /app, so neither the app nor its pnpm tree contributes.
  • This clears 59 of the 87. The 28 that remain all sit on the Node binary, and all are scanner artefacts. See Manual verification.

✏️ Changes

Dockerfile, three edits:

  • Base tag (Dockerfile:4): 24.14.0-alpine3.22 to 24.21.0-alpine3.23. Alpine 3.22 caps Node at 24.16.0, which NVD still lists as affected by the one critical Node CVE. Alpine 3.23 holds musl at 1.2.5, the same minor as 3.22, so the prebuilt sharp binaries see no ABI change. Only 3.24 moves musl to 1.2.6.
  • apk upgrade --no-cache in base: the image ships libssl3 and libcrypto3 at 3.5.7-r0, and the v3.23 branch already serves the 3.5.8-r0 that 10 findings ask for, 2 of them critical. It runs before the existing wget, so that download uses the current OpenSSL. It trades exact reproducibility for those backports.
  • Removals in runtime: the bundled npm and corepack trees, /usr/local/include/node, and their bin symlinks. Nothing calls npm: pnpm is a checksum-verified static binary, and both published stages start through node. The include/node directory holds Node's vendored OpenSSL headers, which 32 findings match. This stays out of base, because build also derives from base and needs the full toolchain.

🧪 Test plan

No automated test covers a Dockerfile, so each done-when item below was checked by hand against the built images.

  • A Node 24 Alpine tag on Dockerfile:4: 24.21.0-alpine3.23. This deviates from the tag the issue names. Node is newer and Alpine is one release lower, to hold musl at 1.2.5.
  • The scan comes back clean, or its residual is listed with a reason: 28 remain, listed under Manual verification.
  • docker build succeeds for every stage: all 6 build (base, build, prod-deps, runtime, migrate, production).
  • node --version in the image: v24.21.0.
  • pnpm test run, pnpm check, pnpm lint: 651 tests pass; 5692 files with 0 errors and 0 warnings; lint clean.
  • The migrate image still runs migrations: Prisma 7.10.0 loads prisma.config.ts and the schema, then fails P1001 against a dead host.
  • sharp still works: sharp 0.35.4 on libvips 8.18.6 encoded and re-read an AVIF image on musl 1.2.5. pnpm build also produced 204 image files.

✅ Manual verification

Scan pr-663-latest in ECR after this merges. Query the linux/arm64 child manifest rather than the tag, because the tag is an OCI index and returns UNSUPPORTED_IMAGE. Expect 28 findings: 1 critical, 8 high, 13 medium, 6 low.

Read those 28 as artefacts before you treat them as work. Each sits on the Node binary, and each carries a fixedInVersion that names Node 25 or 26. Per NVD, the Node 24 line fixed them at 24.14.1, 24.17.0 and 24.19.0, all at or below the 24.21.0 this image runs. The baseline shows the same effect: it reports CVE-2026-21637 against 24.14.0, which NVD records as fixed in 24.13.0.

One environment note: a local docker build behind Cloudflare Gateway fails on TLS, because the proxy CA is absent from the container trust store. That predates this change: pnpm db:generate in build already failed the same way.


🤖 Generated with dx-create-pr

The Inspector scan of `pr-662-latest` reported 87 findings: 5 critical, 44
high, 29 medium, 9 low. Every one traces to the base image. None come from
`/app`, so neither the application nor its pnpm dependencies contribute.

Three changes, measured against that scan:

- Move the base from `node:24.14.0-alpine3.22` to `node:24.21.0-alpine3.23`.
  Alpine 3.22 is the constraint: upstream stopped publishing Node on it in May
  2026, so it caps Node at 24.16.0, which leaves the one critical Node CVE
  genuinely unfixed. Alpine 3.23 keeps `musl` on 1.2.5, the same minor as 3.22,
  so the prebuilt `sharp` binaries see no ABI change. Only 3.24 moves to 1.2.6.

- Add `apk upgrade` to `base`. The image ships OpenSSL 3.5.7-r0 and the branch
  serves 3.5.8-r0, which 10 findings ask for, 2 of them critical.

- Delete the bundled `npm` tree, `corepack`, and `include/node` in `runtime`.
  Nothing calls them, and they account for 53 of the 87 findings.

This clears 59 of 87. The 28 that remain all sit on the Node binary and all
carry a `fixedInVersion` naming Node 25 or 26. Checked against NVD per release
line, they are scanner artefacts: the three cohorts were fixed in Node 24 at
24.14.1, 24.17.0, and 24.19.0, all at or below 24.21.0. The baseline data shows
the same effect, because it reports CVE-2026-21637 against 24.14.0 while NVD
records that one as fixed in 24.13.0.

Verified: all 6 stages build; `node --version` is v24.21.0; OpenSSL reaches
3.5.8-r0; all 6 removed paths are gone and no `opensslv.h` remains; `sharp`
0.35.4 on libvips 8.18.6 encodes AVIF on musl; the migrate image loads Prisma
7.10.0 and reaches the database step; `pnpm test run` passes 651 tests;
`pnpm check` reports 0 errors and 0 warnings; `pnpm lint` is clean.

Refs #656

Co-Authored-By: Claude Opus 5 <[email protected]>
@nicholasjjlim nicholasjjlim self-assigned this Sep 17, 2026
@nicholasjjlim nicholasjjlim added the skill:dx-create-pr Opened with the dx-create-pr skill label Sep 17, 2026
@nicholasjjlim nicholasjjlim changed the title chore(docker): bump the Node base image and strip unused Node parts chore(docker): bump the Node base image to clear container vulnerabilities Sep 17, 2026
@nicholasjjlim
nicholasjjlim marked this pull request as ready for review September 17, 2026 06:35

@ivanfoong ivanfoong left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@nicholasjjlim
nicholasjjlim merged commit f750872 into main Sep 17, 2026
7 checks passed
@nicholasjjlim
nicholasjjlim deleted the chore/bump-node-base-image branch September 17, 2026 06:46
@nicholasjjlim nicholasjjlim mentioned this pull request Sep 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skill:dx-create-pr Opened with the dx-create-pr skill

Projects

None yet

Development

Successfully merging this pull request may close these issues.

chore(docker): bump the Node base image to clear container vulnerabilities

2 participants