Skip to content

Move Docker image off end-of-life Node 18 to Node 24 LTS - #9

Open
coder9io wants to merge 3 commits into
mainfrom
coder9io/issue-8
Open

coder9io wants to merge 3 commits into
mainfrom
coder9io/issue-8

Conversation

@coder9io

@coder9io coder9io commented Oct 21, 2026 •

Copy link
Copy Markdown

First part of the eMudhra Node trust-store remediation. No Node release contains the fix yet, so this PR doesn't close the issue.

What

  • Dockerfile: FROM node:18 → FROM node:24 (active LTS).
  • package.json: added engines.node: ">=24".
  • readme.md: lists Node 24 as a prerequisite.

Why

Node 18 is end-of-life and won't get the SPKI blocklist (nodejs/node@d9a3f3d, nodejs/node#66871, merged 2026-10-20). Per the issue, an EOL major has to move to a supported line now rather than wait for a backport. On the floating node:24 tag, a plain rebuild picks up the 24.x release that carries the backport.

Node execution surfaces (full inventory)

Surface Before After
Container build and runtime (Dockerfile) node:18 node:24
package.json engines none >=24
CI (.github/workflows/docker-image.yml) no setup-node; builds the Dockerfile on release unchanged, inherits node:24
.nvmrc / .node-version / tool-versions none none
docker-compose.yaml builds the Dockerfile unchanged

There are no published npm packages, bundles or CLIs. The only shipped artifact is the image pushed to docker-registry.last9.io by the release workflow.

Release and backport evidence

https://nodejs.org/dist/index.json lists these as the newest releases: v26.12.0 and v24.22.0, both from 2026-10-14. Both predate the 2026-10-20 merge. TLS probe on the newest 24.x:

process.version=v24.22.0
https://dv-g3b-emudhra.we-have-a-problem.com/ -> ACCEPTED (HTTP 200)
https://nodejs.org/ -> ACCEPTED (HTTP 307)

So v24.22.0 is not patched. That is why this PR doesn't pin it as "fixed", and why it only refers to #8 instead of closing it.

Tests

  • No test suite or PR CI exists in this repo (npm test is the default stub). This is a runtime-version change.
  • Smoke run of app.js on v24.22.0 with all env vars set and a dead OTLP endpoint: the app starts, collects the gauges and keeps running. Exports fail with the expected ECONNREFUSED.
  • Not run here: docker build (no Docker in the sandbox). Please build the image once before the next release.
  • 1 commit.

Left for the follow-up

Once Node publishes a 24.x whose release notes include d9a3f3d or its backport:

  1. Pin FROM node:24.<x>.<y> (optionally by digest).
  2. Re-run the TLS probe to show the eMudhra host is rejected and nodejs.org is still accepted.
  3. Rebuild without cache and publish through the release workflow.

TLS verification stays at its default (enabled). No bypasses were added.

Refs #8 (one part; the issue stays open)

Agent usage


Opened by coder9io. Review comments and CI results on this PR are picked up automatically.

Node 18 is EOL and will never get the eMudhra SPKI blocklist (nodejs/node d9a3f3d). Moving to the active LTS line means the next 24.x release carrying the backport reaches this image on a plain rebuild. engines.node documents the supported runtime.

Part of #8: no Node release contains the fix yet; v24.22.0 still accepts the compromised chain.
@coder9io coder9io added the security Security vulnerability or incident label Oct 21, 2026

@reviewer9io reviewer9io left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Reviewed the complete runtime migration at 59346db7a43956eb64cef3a2502a697af862d371, including startup, metric callbacks, exporter configuration, compose and release workflow. No actionable blockers found.

Fresh Node 24.22.0 validation: locked npm ci passed. A native harness loaded the actual app, verified all four gauges across six synthetic workflow/customer combinations, and exercised the actual protobuf exporter against a loopback endpoint: HTTP 400 was reported as failure and the subsequent HTTP 200 export succeeded.

Limits: no Docker build, real vmagent/Levitate, release execution or live TLS check; there are no PR CI checks or substantive existing tests. Application code and locked dependencies are unchanged. This runtime migration leaves the documented certificate-blocklist follow-up outstanding.

@nishantmodak

Copy link
Copy Markdown
Member

@coder9io Do not mark this Ready to merge under security issue #8. The floating Node 24 runtime still accepts the compromised chain and the release image was not built. Wait for patched Node 24, pin its exact image and digest, add PR-time image validation, run smoke/TLS checks, and obtain approval before publishing the rebuilt image.

Issue #8 requires proof that the image's Node rejects the compromised
eMudhra chain and still reaches a trusted endpoint. The check accepts
only CERT_REVOKED, the code the upstream SPKI blocklist reports, so a
DNS failure or unrelated chain error cannot pass as the fix.

It fails on Node 24.22.0, the latest release, which still accepts
the compromised chain.
Base-image changes were only built at release time, so a runtime bump
could ship unverified. Build the image from a clean cache on every PR,
record the Node and OpenSSL versions, smoke-run the app and run the
TLS check. The job uses no secrets and pushes nothing.

Kept in its own commit because it touches .github/workflows.
@coder9io

Copy link
Copy Markdown
Author

@nishantmodak Agreed, this isn't ready to merge. No Node 24 release has the fix yet: 24.22.0 is the latest, and its changelog doesn't contain nodejs/node@d9a3f3d.

This round:

  • da143f0 adds npm run check:tls (scripts/check-tls.js). It records process.version and the OpenSSL version, and passes only if dv-g3b-emudhra.we-have-a-problem.com fails with CERT_REVOKED (the code the upstream blocklist reports) and nodejs.org still connects. On Node 24.22.0 it fails today because the eMudhra host returns 200, which confirms the runtime still accepts the compromised chain.
  • 2c5731f adds PR-time image validation (.github/workflows/pr-image-check.yml). It does an uncached --pull --no-cache build, records the image id and Node version, smoke-runs the app against a dead OTLP endpoint, then runs check:tls inside the image. It uses no secrets and pushes nothing. Docker isn't available in my sandbox, so this job's first run on this PR will also be the first time the image is built. The TLS step is expected to fail until Node ships the fix.

Not done yet: pinning the exact image and digest. There is no patched Node 24 image to pin, and pinning 24.22.0 would lock in the vulnerable runtime. Once the release lands I'll pin node:<24.x.y>@sha256:… plus engines, and post the job's smoke/TLS output here. The release image won't be published without your approval.

@reviewer9io This pushes past your approval, so please re-review da143f0 and 2c5731f.

@coder9io
coder9io requested a review from reviewer9io October 21, 2026 03:12
@coder9io

Copy link
Copy Markdown
Author

CI is red on purpose. Nothing to fix in this PR yet.

  • Build, smoke-run and version steps pass. Only Check TLS trust policy fails: the image's Node still accepts the compromised eMudhra chain (HTTP 200, not CERT_REVOKED). I reproduced this locally on v24.22.0.
  • The blocklist commit (nodejs/node@d9a3f3d) merged on 2026-10-20. That is after every current release: v24.22.0, v26.12.0 and v22.23.3 all lack it. No node:24 tag can pass yet.
  • I left the check as it is and did not pin node:24.22.0, because that would pin a runtime we know is vulnerable.
  • Next step: once a Node 24 release containing d9a3f3d is published, I'll pin FROM node:24.x.y@sha256:<digest> and engines.node to that version and rerun this job. Keep the PR in draft or unmerged until then.

@reviewer9io reviewer9io left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Completed source review of 2c5731fbc991a2bb2991f77e8fe492db3d0f9459, including both new commits, the actual TLS script, PR workflow and Docker/release callers. No additional source defect found.

COMMENT — the image still fails its required TLS trust-policy check. Current-head CI passed the clean image build, runtime recording and application smoke step; Check TLS trust policy failed. Keep the documented patched-image pin/rebuild/TLS follow-up outstanding. This is an observed failing runtime requirement, not merely missing CI.

Eight fresh native probes passed on Node24.22.0 against the real script with synthetic HTTPS outcomes: only CERT_REVOKED plus a successful trusted endpoint passes; accepted compromised chains, unrelated certificate failures, DNS/refused connections and timeouts fail. These tests validate the checker, not the live trust store.

App, lockfile, Docker runtime and compose inputs are Git-identical to the previous complete review; its app/exporter results are reused, not rerun. No local Docker, live TLS, deployment or release execution was performed.

@coder9io

Copy link
Copy Markdown
Author

No change this round; the review found no source defect.

  • Check TLS trust policy is red as expected: nodejs.org/dist/index.json (checked 2026-10-21 03:45 UTC) still lists v26.12.0 and v24.22.0 (2026-10-14) as newest, and neither contains nodejs/node@d9a3f3d. That job is the gate for this PR: it turns green only on an image that carries the blocklist.
  • Follow-up still outstanding: once a 24.x release ships the blocklist, pin node:24.x.y@sha256:… in Dockerfile (currently floating node:24) with matching engines.node (currently >=24), let pr-image-check.yml go green (uncached build, smoke, npm run check:tls), then publish via the release workflow.
  • Note: the PR description predates commits da143f0 and 2c5731f. PR CI (pr-image-check.yml) and scripts/check-tls.js now exist, so the description's "no PR CI" line is out of date. The Dockerfile stays on floating node:24 until a patched release exists to pin. The issue stays open (Refs #8).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

security Security vulnerability or incident

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants