Skip to content

fix(docker): make Node.js use the image's CA certificates - #2823

Merged
Quick104 merged 1 commit into
Silo-Server:mainfrom
blurbery:fix/docker-node-system-ca
Oct 21, 2026
Merged

Quick104 merged 1 commit into
Silo-Server:mainfrom
blurbery:fix/docker-node-system-ca

Conversation

@blurbery

@blurbery blurbery commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Related issue: N/A
Validation tasks: none

The Node.js in the Silo image still trusts the compromised eMudhra intermediate certificates, and a ca-certificates update doesn't change that. Node.js checks TLS against its own bundled CA list, not the system store. Debian's ca-certificates 20250419+deb13u1 removes the two roots in its store that those intermediates chain up to, emSign ECC Root CA - G3 and AAA Certificate Services. The list bundled with Node.js 24.22.0 (the current node:24-slim) has already dropped AAA Certificate Services but still has emSign ECC Root CA - G3, and Node.js hasn't released an updated list yet.

Silo uses this Node.js for the Jellyfin Web installer. When a Jellyfin Web release declares engines.npm, the installer runs npm exec --yes --package=npm@<range>, which downloads that npm release from the registry and checks it only against the integrity value the registry sends over the same connection. Someone who can intercept the server's traffic and holds a registry certificate issued through one of those intermediates could serve a modified npm, which then runs inside the Silo container. Jellyfin Web's own dependencies are less exposed, because npm ci checks them against the hashes in Jellyfin Web's lockfile.

Approach

Set NODE_OPTIONS=--use-openssl-ca in the runtime image, so Node.js reads the same system store as curl, git and apt. Node.js then trusts what Debian's ca-certificates trusts, and a future removal reaches npm with the next image build instead of waiting for a Node.js release.

--use-system-ca doesn't fix this: it adds the system store to the bundled list, and Node.js with that flag still loads the test host below.

The flag only helps in an image built with Debian's patched store. The published build-1559 has ca-certificates 20250419, and Node.js there loads the test host with or without the flag. The next image build picks up the patched store; #2822 unblocks it by getting CI on main green again.

Validation

In throwaway containers from my own image built from the same runtime stage, with ca-certificates 20250419+deb13u1 and Node.js 24.22.0:

  • Without the flag, Node.js fetch and npm view both load https://dv-g3b-emudhra.we-have-a-problem.com/, a test host served through one of the compromised intermediates.
  • With NODE_OPTIONS=--use-openssl-ca, both fail with UNABLE_TO_GET_ISSUER_CERT_LOCALLY, as does fetch to https://dv-g3b-aaa-emudhra.we-have-a-problem.com/, the test host on the AAA Certificate Services path. fetch to registry.npmjs.org and github.com still works, and the installer's path, npm exec --yes --package="npm@>=11.6.0 <12" -- npm --version, downloads and runs npm 11.21.1.
  • Jellyfin Web v12.2's dependency install, run the way the installer runs it (npm exec --yes --package="npm@>=11.0.0" -- npm ci), completes with the flag and installs 1,771 packages.
  • Not run: the npm run build:production step, which doesn't use the network, and a local build of this branch's image.
  • This branch's CI: every check passes on 4fcbed1 (run).

Evidence

Evidence: none, no user-visible change

A Jellyfin Web install looks and behaves the same as before. It only differs when someone intercepts the connection with a certificate from these intermediates: npm then stops with a certificate error instead of installing, which the Validation section shows against the test hosts.

Risks

Every Node.js process in the container, which today means the Jellyfin Web installer, trusts exactly Debian's store instead of Node.js's bundled list. Both follow Mozilla's root store, so registry.npmjs.org and GitHub are unaffected. An operator who sets their own NODE_OPTIONS replaces this value, as with any image ENV.

Checklist

  • I read and can explain the complete diff.
  • This pull request addresses one concern.
  • The Evidence section shows every change a user can see, or says there is none.

AI Disclosure

  • Harness: Claude Code (Claude desktop app)
  • Tool(s): Claude Code
  • Model(s): claude-opus-5-5
  • Involvement: AI-assisted with Claude Opus. I directed the task and designed the work.
  • Adversarial review: n/a, a one-line image setting checked by the container tests above

The runtime image copies Node.js from node:24-slim for the Jellyfin Web
installer. Node.js verifies TLS against its own bundled CA list, so
Debian's ca-certificates updates never reach it. Debian's
20250419+deb13u1 drops the emSign ECC Root CA - G3 that the
compromised eMudhra intermediates chain to; the list bundled with
Node.js 24.22.0 still trusts it.

The installer runs npm exec for the npm release a Jellyfin Web version
declares in engines.npm. npm checks that download only against the
integrity value the registry sends over the same connection, so a
forged registry certificate would let someone on the network path serve
a modified npm that then runs inside the Silo container.

Set NODE_OPTIONS=--use-openssl-ca so Node.js uses the system store that
curl, git and apt already use.
@silo-triage silo-triage Bot added the size/S 0–49 added + deleted lines (all files); change volume, not priority. label Oct 21, 2026
@silo-kody

silo-kody Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Silo Kody — review complete

Review finished. Check the inline comments for findings and verify each suggestion against the code and tests.

Reviewing changes in Silo
  • Include the related issue, expected behavior, and validation steps in the PR description.
  • For API changes, describe the effect on Apple and Android clients and Jellyfin compatibility.
  • For plugin changes, identify the affected SDK contract, plugin, and catalog entry.
  • Follow this repository's AGENTS.md and CONTRIBUTING.md.
  • Request another review with @kody start-review in a PR comment.
  • React with 👍 or 👎 to give feedback on individual suggestions.
Review settings
Review Options

The following review options are enabled or disabled:

Options Enabled
Bug ✅
Performance ✅
Security ✅
Business Logic ❌
⚠️ 1 Kody Rule(s) were not evaluated

These rules declare that they need repository context beyond this diff, and the review could not retrieve it, so they were not judged on this pull request:

  • Preserve optional store capabilities through production wrappers

@silo-triage silo-triage Bot added bug Something isn't working impact: security Auth, privacy, or permission boundary priority: P0 Fix/merge first: data-loss, security, or widespread breakage labels Oct 21, 2026
@macroscopeapp

macroscopeapp Bot commented Oct 21, 2026

Copy link
Copy Markdown

Dockerfile changes the Jellyfin Web installer’s npm trust policy, which can change the admin-visible install result (completion versus TLS failure); the Evidence section has no before-and-after capture of that result. Add a recording of the same installer flow under the affected certificate condition, and identify the admin surface and build/commit.

Suggested fix: Add before-and-after evidence of the Jellyfin Web install flow under Evidence.

Automated check: Macroscope check run agent (gpt-6-luna). Evidence was not reviewed for correctness.

Posted via Macroscope — Visible change evidence

@coderabbitai

coderabbitai Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 6fb3fe46-f762-4177-b137-63c9d66240f9
📥 Commits

Reviewing files that changed from the base of the PR and between 174fb9a and 4fcbed1.

📒 Files selected for processing: 1
  • Dockerfile

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 2 remain after this review.

📝 Walkthrough

The Dockerfile sets NODE_OPTIONS=--use-openssl-ca so Node.js and npm use Debian’s system CA store.

Changes: Runtime CA configuration

Layer / File(s) Summary
Configure the Node.js CA store
Dockerfile
The runtime image sets NODE_OPTIONS=--use-openssl-ca.

Priority: ⬇️ Low

Estimated code review effort: 1 (Trivial) | ~3 minutes

Change: Bug fix

Suggested reviewers: quick104

Merge Risk: ⚪ Minimal · up to 4fcbe

No concrete merge-blocking issue was found in the Dockerfile change.

Pre-merge checks: Passed 5
Check name Status Explanation
Title check Passed The title clearly and concisely describes the main change: making Node.js use the Docker image's CA certificates.
Docstring Coverage Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Description check Passed The pull request description directly explains the Dockerfile change, its security purpose, implementation, validation, risks, and limitations.
Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0 files. (1 skipped: 1 unsupported.)

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@Quick104
Quick104 merged commit 3abb637 into Silo-Server:main Oct 21, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working impact: security Auth, privacy, or permission boundary priority: P0 Fix/merge first: data-loss, security, or widespread breakage size/S 0–49 added + deleted lines (all files); change volume, not priority.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants