Skip to content

Commit 4e7dee6

Browse files
ericallamTrigger.dev RepoOps
authored andcommitted
fix(webapp): distrust roots that chain to the compromised eMudhra intermediates
The webapp Docker image no longer trusts the roots behind the eight eMudhra intermediate CAs whose private keys were compromised ([background](https://emudhra.we-have-a-problem.com/)): emSign ECC Root CA - G3, emSign Root CA - C1, emSign ECC Root CA - C3, and Sectigo's AAA Certificate Services, which cross-signs the same intermediates. The system CA bundle drops them for OpenSSL, goose and Prisma's engines. A small preload removes them from Node's bundled roots, since no Node release has done that yet ([nodejs/node#66871](nodejs/node#66871)). The image loads it through `NODE_OPTIONS`, and the entrypoint keeps it when `NODE_OPTIONS` is overridden at deploy time. Certificates added with `NODE_EXTRA_CA_CERTS` are kept. Mono-RevId: 28fb41176a5984be06fe3755f5fa4447e05d399f
1 parent 99ea130 commit 4e7dee6

5 files changed

Lines changed: 56 additions & 0 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
area: webapp
3+
type: fix
4+
---
5+
6+
The webapp Docker image no longer trusts the root certificates that chain to the compromised eMudhra intermediate CAs, so connections to servers presenting certificates from those intermediates now fail.

‎docker/Dockerfile‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,16 @@ RUN --mount=type=secret,id=sentry_auth_token \
8989
FROM ${NODE_IMAGE} AS runner
9090
ARG APT_REFRESH
9191
RUN echo "apt refresh ${APT_REFRESH}" && apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends openssl netcat-openbsd ca-certificates && rm -rf /var/lib/apt/lists/*
92+
# Distrust the roots that chain to the compromised eMudhra intermediates (Oct 2026). The system
93+
# bundle covers OpenSSL, goose and Prisma's engines; distrust-cas.cjs does the same for Node's
94+
# bundled roots. Both can go once Debian's ca-certificates and Node drop these roots.
95+
RUN sed -i -E \
96+
-e 's#^(mozilla/emSign_(ECC_Root_CA_-_G3|Root_CA_-_C1|ECC_Root_CA_-_C3)\.crt)$#!\1#' \
97+
-e 's#^mozilla/Comodo_AAA_Services_root\.crt$#!&#' \
98+
/etc/ca-certificates.conf && update-ca-certificates --fresh
9299
WORKDIR /triggerdotdev
93100
ENV NODE_ENV=production
101+
ENV NODE_OPTIONS=--require=/triggerdotdev/scripts/distrust-cas.cjs
94102

95103
COPY --from=base /usr/bin/dumb-init /usr/bin/dumb-init
96104
COPY --from=pruner --chown=node:node /triggerdotdev/out/full/ .

‎docker/scripts/distrust-cas.cjs‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
const tls = require("node:tls");
2+
const { X509Certificate } = require("node:crypto");
3+
4+
const DISTRUSTED = new Map([
5+
[
6+
"7D:D7:8D:5F:4F:13:45:9A:83:DF:F9:AB:BB:A6:2E:DB:AF:6F:2D:10:2B:F2:57:FD:71:2F:4D:9F:27:46:ED:8D",
7+
"emSign Root TLS CA - G3",
8+
],
9+
[
10+
"F2:ED:AA:FF:3D:9B:70:1F:B4:D1:4C:9F:28:5F:8C:0B:AD:90:FC:3B:CC:1F:A0:7D:47:F4:71:8E:DA:BA:34:A5",
11+
"emSign Root CS CA - G3",
12+
],
13+
[
14+
"D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4",
15+
"AAA Certificate Services",
16+
],
17+
[
18+
"86:A1:EC:BA:08:9C:4A:8D:3B:BE:27:34:C6:12:BA:34:1D:81:3E:04:3C:F9:E8:A8:62:CD:5C:57:A3:6B:BE:6B",
19+
"emSign ECC Root CA - G3",
20+
],
21+
[
22+
"12:56:09:AA:30:1D:A0:A2:49:B9:7A:82:39:CB:6A:34:21:6F:44:DC:AC:9F:39:54:B1:42:92:F2:E8:C8:60:8F",
23+
"emSign Root CA - C1",
24+
],
25+
[
26+
"BC:4D:80:9B:15:18:9D:78:DB:3E:1D:8C:F4:F9:72:6A:79:5D:A1:64:3C:A5:F1:35:8E:1D:DB:0E:DC:0D:7E:B3",
27+
"emSign ECC Root CA - C3",
28+
],
29+
]);
30+
31+
tls.setDefaultCACertificates(
32+
tls
33+
.getCACertificates("default")
34+
.filter((pem) => !DISTRUSTED.has(new X509Certificate(pem).fingerprint256))
35+
);

‎docker/scripts/entrypoint.sh‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
#!/bin/sh
22
set -xe
33

4+
# A NODE_OPTIONS set at deploy time replaces the image's, so keep the CA distrust preload on it.
5+
case " ${NODE_OPTIONS:-} " in
6+
*" --require=/triggerdotdev/scripts/distrust-cas.cjs "*) ;;
7+
*) export NODE_OPTIONS="--require=/triggerdotdev/scripts/distrust-cas.cjs${NODE_OPTIONS:+ $NODE_OPTIONS}" ;;
8+
esac
9+
410
if [ -n "$DATABASE_HOST" ]; then
511
scripts/wait-for-it.sh ${DATABASE_HOST} -- echo "database is up"
612
fi

‎knip.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export default {
88
".": {
99
entry: [
1010
"scripts/**/*.{js,mjs,cjs,ts,mts,cts}",
11+
"docker/scripts/distrust-cas.cjs",
1112
"vitest.internal.config.ts",
1213
"vitest.internal-reports.config.mjs",
1314
],

0 commit comments

Comments
 (0)