From e7a1d61e5f2439aecb6f3a10693e28f06fbacedd Mon Sep 17 00:00:00 2001 From: Jeremy Daer Date: Wed, 21 Oct 2026 13:02:04 -0700 Subject: [PATCH] Update the trusted CA certificates Install ca-certificates in the base stage, before the build stage fetches gems, so the image takes the distribution's current package rather than the one in the base image, and fail the build if either withdrawn root (emSign ECC Root CA - G3, AAA Certificate Services) is still in the store Ruby's OpenSSL loads. --- Dockerfile | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Dockerfile b/Dockerfile index 6e4d2d96..02a9d584 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,6 +13,23 @@ ENV RAILS_ENV="production" \ BUNDLE_PATH="/usr/local/bundle" \ BUNDLE_WITHOUT="development" +# Install the distribution's current trusted roots rather than the ones frozen into the base image +RUN apt-get update -qq && \ + apt-get install --no-install-recommends -y ca-certificates && \ + rm -rf /var/lib/apt/lists /var/cache/apt/archives + +# Fail the build if either of these withdrawn roots is still where Ruby's OpenSSL looks for +# trusted certificates +RUN ruby -ropenssl -e ' \ + file = ENV[OpenSSL::X509::DEFAULT_CERT_FILE_ENV] || OpenSSL::X509::DEFAULT_CERT_FILE; \ + dir = ENV[OpenSSL::X509::DEFAULT_CERT_DIR_ENV] || OpenSSL::X509::DEFAULT_CERT_DIR; \ + pems = [file, *Dir.glob(File.join(dir, "*"))].select { |path| File.file?(path) } \ + .flat_map { |path| File.read(path).scan(/-----BEGIN CERTIFICATE-----.+?-----END CERTIFICATE-----/m) }; \ + subjects = pems.map { |pem| OpenSSL::X509::Certificate.new(pem).subject.to_s }.uniq; \ + abort "Only #{subjects.size} roots in #{file} and #{dir}" if subjects.size < 100; \ + withdrawn = subjects.grep(%r{/CN=(emSign ECC Root CA - G3|AAA Certificate Services)\z}); \ + abort "Withdrawn roots still trusted: #{withdrawn}" if withdrawn.any?' + # Throw-away build stage to reduce size of final image FROM --platform=$TARGETPLATFORM base as build