From f9e44bd424a201c3da698323c767454c55c20e5c Mon Sep 17 00:00:00 2001 From: Eliott B <47679741+eliottness@users.noreply.github.com> Date: Fri, 23 Oct 2026 19:55:24 +0200 Subject: [PATCH 1/3] Stop trusting compromised eMudhra roots in CI images Move the JDK test images from alpine 3.19 to alpine 3.24.3, route NSS through p11-kit, and drop the emSign root from the copied Temurin JDKs while they still ship it. The musl native-binary image stays on alpine 3.11 for musl compatibility and has both roots removed in place (IR-62343). CentOS 6/7 and manylinux images are follow-ups. Jira: APPSEC-71286 --- ci/alpine-stock8/Dockerfile | 7 +++++-- ci/alpine-temurin21/Dockerfile | 12 ++++++++++-- ci/alpine-temurin25/Dockerfile | 12 ++++++++++-- ci/alpine/Dockerfile | 8 ++++++++ 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/ci/alpine-stock8/Dockerfile b/ci/alpine-stock8/Dockerfile index 688819db..62465602 100644 --- a/ci/alpine-stock8/Dockerfile +++ b/ci/alpine-stock8/Dockerfile @@ -1,5 +1,8 @@ -FROM alpine:3.19 -RUN apk add --no-cache bash openjdk8 +FROM alpine:3.24.3 +RUN apk add --no-cache bash openjdk8 p11-kit-trust && \ + for module in /usr/lib/libnssckbi.so*; do \ + ln -sf /usr/lib/pkcs11/p11-kit-trust.so "$module"; \ + done ENV JAVA_HOME=/usr/lib/jvm/java-1.8-openjdk ENV JAVA_8_HOME=/usr/lib/jvm/java-1.8-openjdk ENV PATH=$JAVA_HOME/bin:$PATH diff --git a/ci/alpine-temurin21/Dockerfile b/ci/alpine-temurin21/Dockerfile index eb799cf8..d9d1dd9d 100644 --- a/ci/alpine-temurin21/Dockerfile +++ b/ci/alpine-temurin21/Dockerfile @@ -1,7 +1,15 @@ -FROM alpine:3.19 +FROM alpine:3.24.3 # JDK 8 retained for build toolchain compatibility (sourceCompatibility = 1.8) -RUN apk add --no-cache bash openjdk8 +RUN apk add --no-cache bash openjdk8 p11-kit-trust && \ + for module in /usr/lib/libnssckbi.so*; do \ + ln -sf /usr/lib/pkcs11/p11-kit-trust.so "$module"; \ + done COPY --from=eclipse-temurin:21-jdk-alpine /opt/java/openjdk /usr/lib/jvm/21 +# Delete the emSign ECC G3 root only while the copied JDK still ships it (the Oct-21 JDK update removes it). +RUN KS=/usr/lib/jvm/21/lib/security/cacerts; A="cn_emsign_ecc_root_ca__g3,o_emudhra_technologies_limited,ou_emsign_pki,c_in [jdk]"; \ + if /usr/lib/jvm/21/bin/keytool -list -keystore "$KS" -storepass changeit -alias "$A" >/dev/null 2>&1; then \ + /usr/lib/jvm/21/bin/keytool -delete -keystore "$KS" -storepass changeit -alias "$A"; \ + fi ENV JAVA_HOME=/usr/lib/jvm/java-1.8-openjdk ENV JAVA_8_HOME=/usr/lib/jvm/java-1.8-openjdk ENV JAVA_21_HOME=/usr/lib/jvm/21 diff --git a/ci/alpine-temurin25/Dockerfile b/ci/alpine-temurin25/Dockerfile index dfc2f77a..3d315dd8 100644 --- a/ci/alpine-temurin25/Dockerfile +++ b/ci/alpine-temurin25/Dockerfile @@ -1,7 +1,15 @@ -FROM alpine:3.19 +FROM alpine:3.24.3 # JDK 8 retained for build toolchain compatibility (sourceCompatibility = 1.8) -RUN apk add --no-cache bash openjdk8 +RUN apk add --no-cache bash openjdk8 p11-kit-trust && \ + for module in /usr/lib/libnssckbi.so*; do \ + ln -sf /usr/lib/pkcs11/p11-kit-trust.so "$module"; \ + done COPY --from=eclipse-temurin:25-jdk-alpine /opt/java/openjdk /usr/lib/jvm/25 +# Delete the emSign ECC G3 root only while the copied JDK still ships it (the Oct-21 JDK update removes it). +RUN KS=/usr/lib/jvm/25/lib/security/cacerts; A="cn_emsign_ecc_root_ca__g3,o_emudhra_technologies_limited,ou_emsign_pki,c_in [jdk]"; \ + if /usr/lib/jvm/25/bin/keytool -list -keystore "$KS" -storepass changeit -alias "$A" >/dev/null 2>&1; then \ + /usr/lib/jvm/25/bin/keytool -delete -keystore "$KS" -storepass changeit -alias "$A"; \ + fi ENV JAVA_HOME=/usr/lib/jvm/java-1.8-openjdk ENV JAVA_8_HOME=/usr/lib/jvm/java-1.8-openjdk ENV JAVA_25_HOME=/usr/lib/jvm/25 diff --git a/ci/alpine/Dockerfile b/ci/alpine/Dockerfile index 33910edb..2209a0fb 100644 --- a/ci/alpine/Dockerfile +++ b/ci/alpine/Dockerfile @@ -1,5 +1,13 @@ FROM alpine:3.11 +# Alpine 3.11 is kept on purpose: the musl native binaries built here must run on old musl. +# It gets no fixed ca-certificates package, so remove both compromised eMudhra roots in place. +RUN apk add --no-cache ca-certificates \ + && sed -i -e 's|^mozilla/emSign_ECC_Root_CA_-_G3.crt|!&|' -e 's|^mozilla/Comodo_AAA_Services_root.crt|!&|' /etc/ca-certificates.conf \ + && rm -f /usr/share/ca-certificates/mozilla/emSign_ECC_Root_CA_-_G3.crt /usr/share/ca-certificates/mozilla/Comodo_AAA_Services_root.crt \ + && update-ca-certificates \ + && ln -sf /etc/ssl/certs/ca-certificates.crt /etc/ssl/cert.pem + RUN apk add --update-cache --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing cmake bash make git g++ wget openjdk8 ENV JAVA_HOME=/usr/lib/jvm/java-1.8-openjdk From 69677cd9bf1c79aaa8b6f8af00874a04939aa5e1 Mon Sep 17 00:00:00 2001 From: Eliott B <47679741+eliottness@users.noreply.github.com> Date: Tue, 27 Oct 2026 10:56:25 +0100 Subject: [PATCH 2/3] Redirect NSS builtin roots in Alpine CI images openjdk8 depends on nss, and NSS compiles its builtin roots into /usr/lib/libnssckbi.so* and the test copy /usr/lib/libnssckbi-testlib.so*. Both still carry emSign ECC Root CA - G3 and AAA Certificate Services. - ci/alpine (Alpine 3.11): install p11-kit-trust after openjdk8, point the libnssckbi.so* modules at /usr/lib/pkcs11/p11-kit-trust.so, and remove libnssckbi-testlib.so*. - ci/alpine-stock8, ci/alpine-temurin21, ci/alpine-temurin25 (Alpine 3.24.3): also remove libnssckbi-testlib.so*. nss 3.124-r0 in v3.24 ships libnssckbi-testlib.so.124, which the existing libnssckbi.so* glob misses. Jira: APPSEC-71286 --- ci/alpine-stock8/Dockerfile | 3 ++- ci/alpine-temurin21/Dockerfile | 3 ++- ci/alpine-temurin25/Dockerfile | 3 ++- ci/alpine/Dockerfile | 8 +++++++- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/ci/alpine-stock8/Dockerfile b/ci/alpine-stock8/Dockerfile index 62465602..22bb2aa5 100644 --- a/ci/alpine-stock8/Dockerfile +++ b/ci/alpine-stock8/Dockerfile @@ -2,7 +2,8 @@ FROM alpine:3.24.3 RUN apk add --no-cache bash openjdk8 p11-kit-trust && \ for module in /usr/lib/libnssckbi.so*; do \ ln -sf /usr/lib/pkcs11/p11-kit-trust.so "$module"; \ - done + done && \ + rm -f /usr/lib/libnssckbi-testlib.so* ENV JAVA_HOME=/usr/lib/jvm/java-1.8-openjdk ENV JAVA_8_HOME=/usr/lib/jvm/java-1.8-openjdk ENV PATH=$JAVA_HOME/bin:$PATH diff --git a/ci/alpine-temurin21/Dockerfile b/ci/alpine-temurin21/Dockerfile index d9d1dd9d..f9da80f3 100644 --- a/ci/alpine-temurin21/Dockerfile +++ b/ci/alpine-temurin21/Dockerfile @@ -3,7 +3,8 @@ FROM alpine:3.24.3 RUN apk add --no-cache bash openjdk8 p11-kit-trust && \ for module in /usr/lib/libnssckbi.so*; do \ ln -sf /usr/lib/pkcs11/p11-kit-trust.so "$module"; \ - done + done && \ + rm -f /usr/lib/libnssckbi-testlib.so* COPY --from=eclipse-temurin:21-jdk-alpine /opt/java/openjdk /usr/lib/jvm/21 # Delete the emSign ECC G3 root only while the copied JDK still ships it (the Oct-21 JDK update removes it). RUN KS=/usr/lib/jvm/21/lib/security/cacerts; A="cn_emsign_ecc_root_ca__g3,o_emudhra_technologies_limited,ou_emsign_pki,c_in [jdk]"; \ diff --git a/ci/alpine-temurin25/Dockerfile b/ci/alpine-temurin25/Dockerfile index 3d315dd8..f531bbd5 100644 --- a/ci/alpine-temurin25/Dockerfile +++ b/ci/alpine-temurin25/Dockerfile @@ -3,7 +3,8 @@ FROM alpine:3.24.3 RUN apk add --no-cache bash openjdk8 p11-kit-trust && \ for module in /usr/lib/libnssckbi.so*; do \ ln -sf /usr/lib/pkcs11/p11-kit-trust.so "$module"; \ - done + done && \ + rm -f /usr/lib/libnssckbi-testlib.so* COPY --from=eclipse-temurin:25-jdk-alpine /opt/java/openjdk /usr/lib/jvm/25 # Delete the emSign ECC G3 root only while the copied JDK still ships it (the Oct-21 JDK update removes it). RUN KS=/usr/lib/jvm/25/lib/security/cacerts; A="cn_emsign_ecc_root_ca__g3,o_emudhra_technologies_limited,ou_emsign_pki,c_in [jdk]"; \ diff --git a/ci/alpine/Dockerfile b/ci/alpine/Dockerfile index 2209a0fb..5f995d4e 100644 --- a/ci/alpine/Dockerfile +++ b/ci/alpine/Dockerfile @@ -8,7 +8,13 @@ RUN apk add --no-cache ca-certificates \ && update-ca-certificates \ && ln -sf /etc/ssl/certs/ca-certificates.crt /etc/ssl/cert.pem -RUN apk add --update-cache --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing cmake bash make git g++ wget openjdk8 +# openjdk8 pulls in nss, whose builtin roots module still trusts both roots: point it at the +# p11-kit trust module (system bundle) and drop the NSS test copy of the builtins. +RUN apk add --update-cache --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing cmake bash make git g++ wget openjdk8 p11-kit-trust \ + && for module in /usr/lib/libnssckbi.so*; do \ + ln -sf /usr/lib/pkcs11/p11-kit-trust.so "$module"; \ + done \ + && rm -f /usr/lib/libnssckbi-testlib.so* ENV JAVA_HOME=/usr/lib/jvm/java-1.8-openjdk ENV PATH=$JAVA_HOME/bin:$PATH From f08ad3540ded0c8b88a01dc117ee8b538c717363 Mon Sep 17 00:00:00 2001 From: Eliott B <47679741+eliottness@users.noreply.github.com> Date: Tue, 27 Oct 2026 10:56:50 +0100 Subject: [PATCH 3/3] Assert compromised roots are gone from Temurin cacerts The previous step deleted one hard-coded alias and silently skipped when the alias did not match, which would leave the root trusted if Temurin renamed the entry. Now, in ci/alpine-temurin21 and ci/alpine-temurin25: - find entries whose Owner is CN=emSign ECC Root CA - G3 or CN=AAA Certificate Services and delete them by alias; - list the store again and fail the build if either subject is still there. eclipse-temurin:21-jdk-alpine (jdk-21.0.12.1+1) and :25-jdk-alpine (jdk-25.0.4.1+1) still ship emSign ECC G3. Temurin 21.0.13+9 and 25.0.5+8 (2026-10-22) ship neither root, so the step becomes a no-op guard once the Docker Hub tags move. Jira: APPSEC-71286 --- ci/alpine-temurin21/Dockerfile | 15 ++++++++++----- ci/alpine-temurin25/Dockerfile | 15 ++++++++++----- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/ci/alpine-temurin21/Dockerfile b/ci/alpine-temurin21/Dockerfile index f9da80f3..f17f9503 100644 --- a/ci/alpine-temurin21/Dockerfile +++ b/ci/alpine-temurin21/Dockerfile @@ -6,11 +6,16 @@ RUN apk add --no-cache bash openjdk8 p11-kit-trust && \ done && \ rm -f /usr/lib/libnssckbi-testlib.so* COPY --from=eclipse-temurin:21-jdk-alpine /opt/java/openjdk /usr/lib/jvm/21 -# Delete the emSign ECC G3 root only while the copied JDK still ships it (the Oct-21 JDK update removes it). -RUN KS=/usr/lib/jvm/21/lib/security/cacerts; A="cn_emsign_ecc_root_ca__g3,o_emudhra_technologies_limited,ou_emsign_pki,c_in [jdk]"; \ - if /usr/lib/jvm/21/bin/keytool -list -keystore "$KS" -storepass changeit -alias "$A" >/dev/null 2>&1; then \ - /usr/lib/jvm/21/bin/keytool -delete -keystore "$KS" -storepass changeit -alias "$A"; \ - fi +# Delete both compromised roots from the copied JDK cacerts by subject (not alias), then fail the +# build if either is still there. The current eclipse-temurin:21-jdk-alpine tag still ships emSign +# ECC G3; the Oct-21 Temurin release drops it, and then this step deletes nothing. +RUN set -e; KT=/usr/lib/jvm/21/bin/keytool; KS=/usr/lib/jvm/21/lib/security/cacerts; \ + BAD='^Owner: CN=(emSign ECC Root CA - G3|AAA Certificate Services),'; \ + LIST=$("$KT" -list -v -keystore "$KS" -storepass changeit); \ + printf '%s\n' "$LIST" | awk -v bad="$BAD" '/^Alias name: /{a=substr($0,13)} $0 ~ bad {print a}' | \ + while IFS= read -r alias; do "$KT" -delete -keystore "$KS" -storepass changeit -alias "$alias"; done; \ + LIST=$("$KT" -list -v -keystore "$KS" -storepass changeit); \ + if printf '%s\n' "$LIST" | grep -Eq "$BAD"; then echo "compromised root still in $KS" >&2; exit 1; fi ENV JAVA_HOME=/usr/lib/jvm/java-1.8-openjdk ENV JAVA_8_HOME=/usr/lib/jvm/java-1.8-openjdk ENV JAVA_21_HOME=/usr/lib/jvm/21 diff --git a/ci/alpine-temurin25/Dockerfile b/ci/alpine-temurin25/Dockerfile index f531bbd5..0350e3f3 100644 --- a/ci/alpine-temurin25/Dockerfile +++ b/ci/alpine-temurin25/Dockerfile @@ -6,11 +6,16 @@ RUN apk add --no-cache bash openjdk8 p11-kit-trust && \ done && \ rm -f /usr/lib/libnssckbi-testlib.so* COPY --from=eclipse-temurin:25-jdk-alpine /opt/java/openjdk /usr/lib/jvm/25 -# Delete the emSign ECC G3 root only while the copied JDK still ships it (the Oct-21 JDK update removes it). -RUN KS=/usr/lib/jvm/25/lib/security/cacerts; A="cn_emsign_ecc_root_ca__g3,o_emudhra_technologies_limited,ou_emsign_pki,c_in [jdk]"; \ - if /usr/lib/jvm/25/bin/keytool -list -keystore "$KS" -storepass changeit -alias "$A" >/dev/null 2>&1; then \ - /usr/lib/jvm/25/bin/keytool -delete -keystore "$KS" -storepass changeit -alias "$A"; \ - fi +# Delete both compromised roots from the copied JDK cacerts by subject (not alias), then fail the +# build if either is still there. The current eclipse-temurin:25-jdk-alpine tag still ships emSign +# ECC G3; the Oct-21 Temurin release drops it, and then this step deletes nothing. +RUN set -e; KT=/usr/lib/jvm/25/bin/keytool; KS=/usr/lib/jvm/25/lib/security/cacerts; \ + BAD='^Owner: CN=(emSign ECC Root CA - G3|AAA Certificate Services),'; \ + LIST=$("$KT" -list -v -keystore "$KS" -storepass changeit); \ + printf '%s\n' "$LIST" | awk -v bad="$BAD" '/^Alias name: /{a=substr($0,13)} $0 ~ bad {print a}' | \ + while IFS= read -r alias; do "$KT" -delete -keystore "$KS" -storepass changeit -alias "$alias"; done; \ + LIST=$("$KT" -list -v -keystore "$KS" -storepass changeit); \ + if printf '%s\n' "$LIST" | grep -Eq "$BAD"; then echo "compromised root still in $KS" >&2; exit 1; fi ENV JAVA_HOME=/usr/lib/jvm/java-1.8-openjdk ENV JAVA_8_HOME=/usr/lib/jvm/java-1.8-openjdk ENV JAVA_25_HOME=/usr/lib/jvm/25