Skip to content

Bump Docker base to node:24.22.1-slim and use the OS CA store - #515

Merged
chrapkowski-sg merged 1 commit into
mainfrom
fix/node-ca-store-emudhra
Oct 22, 2026
Merged

chrapkowski-sg merged 1 commit into
mainfrom
fix/node-ca-store-emudhra

Conversation

@chrapkowski-sg

Copy link
Copy Markdown
Contributor

The eMudhra intermediate CA key has been compromised. Node 24.19.0, which the current image is based on, still trusts chains issued under it through emSign ECC Root CA - G3 in its bundled CA store. Package installs during auto-indexing (npm, yarn, pnpm) go through Node, so they accept those certificates even though the Debian trust store in the image (used by curl, git and Python) already rejects them.

Changes:

  • Bump the base image to node:24.22.1-slim (index digest sha256:55fb5f5a…d205), whose bundled CA store no longer trusts the affected chains. .tool-versions is updated to match.
  • Add --use-openssl-ca to NODE_OPTIONS so Node uses the patched Debian CA store instead of the CA list compiled into the binary. Auto-indexing runs n install auto when a repository pins a Node version (.nvmrc, .node-version, engines.node), and those older Node binaries carry their own unpatched CA lists. Without this flag, Node 22.12.0 installed this way accepted both the emSign ECC Root CA - G3 chain and the Comodo AAA Certificate Services cross-signed chain.

Test plan

Built the image locally and connected to test hosts serving a leaf certificate under the compromised intermediate, one chaining to emSign ECC Root CA - G3 and one through the Comodo AAA Certificate Services cross-sign. A certificate error counts as a pass. As controls, untrusted-root.badssl.com must fail and registry.npmjs.org must succeed.

Client Current image (emSign / AAA) This PR (emSign / AAA)
node https.get accepted / rejected rejected (CERT_REVOKED) / rejected
npm install accepted / rejected rejected / rejected
yarn add accepted / rejected rejected / rejected
pnpm add accepted / rejected rejected / rejected
curl, git, python3 rejected / rejected rejected / rejected
  • After n install auto installed Node 16.20.2, 18.20.8, 20.11.0 and 22.12.0, Node, npm and yarn reject both chains (UNABLE_TO_GET_ISSUER_CERT_LOCALLY), and registry.npmjs.org and registry.yarnpkg.com still work.
  • Indexed a small TypeScript project with dependencies (lodash, zod, @types/lodash) using npm install and scip-typescript index, on the preinstalled Node and on Node installed by n install auto. The resulting index.scip is byte-identical to the one produced by the current image, and it contains the dependency symbols.
  • yarn install --frozen-lockfile && yarn build && yarn test inside the new image: 38/38 tests pass.

Node 24.19.0's bundled CA store still trusts certificate chains issued
under the compromised eMudhra intermediate CA (via emSign ECC Root CA - G3).
Node 24.22.1 ships a CA store without the affected roots.

Also run Node with --use-openssl-ca so that Node versions installed by
`n install auto` during auto-indexing use the patched Debian CA store
instead of their own bundled CA lists, which cannot be patched.
@chrapkowski-sg
chrapkowski-sg merged commit 8a40666 into main Oct 22, 2026
5 checks passed
@chrapkowski-sg
chrapkowski-sg deleted the fix/node-ca-store-emudhra branch October 22, 2026 11:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants