Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Mission Possible: The 45-Minute Path to Bullet-...

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

Mission Possible: The 45-Minute Path to Bullet-Proof Java Container Images

Your mission is to turn a bloated CVE-infested container image into a hardened low-noise image with low vulnerability exposure and clear operational posture. You have 45 minutes before the explosive attack hits. Mission possible!
This session provides a straight path towards building more secure and maintainable Java container images. We will identify the key culprits such as stale dependencies, outdated base, lack of provenance, and excessive privileges. Then, we will draft a step-by-step plan to:
- Pick a minimal and well-maintained base image,
- Shrink privileges,
- Prove provenance with version pinning, signatures and SBOMs,
- Scan and classify with CVSS rules to cut noise and fix what’s exploitable,
- Automatically monitor for updates.
Expect a before/after scan comparison, copy-and-paste Dockerfile instructions, verification checklist, and a clear and reproducible path towards hardened Java container images that provide an impenetrable lock-box for your applications.

Avatar for Catherine

Catherine

April 09, 2026

More Decks by Catherine

Other Decks in Programming

Transcript

  1. You’re sealed in a dark room. Water is pouring from

    the ceiling. Somewhere in that water is a danger. You’ve got 45 minutes to save the world. YOUR CONTAINER IMAGE CVE FLOW EXPLOITABLE CVE
  2. MISSION BRIEFING OBJECTIVE Ship a low-noise image with zero unmanaged

    risk. RULES OF ENGAGEMENT Fix real exposure Success means an image you can verify, patch, and control.
  3. FIELD PROCEDURE 1. Limit privileges 2. Shrink 3. Classify risk

    4. Patch 5. Prove origin ROUTE APPROVED
  4. Initial Dockerfile FROM eclipse-temurin:25-jdk as builder WORKDIR /app COPY .

    /app/app RUN cd app && ./mvnw package EXPOSE 8080 ENTRYPOINT ["java","-jar","/app/app/target/*.jar"] Final image: 1GB
  5. What if we set the scanners loose? osv-scanner scan image

    app:latest Total 19 packages affected by 46 known vulnerabilities 4 42 APP LAYER BASE LAYER
  6. Could be worse… trivy image openjdk:25-ea Report Summary ┌────────────────────────────┬────────┬─────────────────┬─────────┐ │

    Target │ Type │ Vulnerabilities │ Secrets │ ├────────────────────────────┼────────┼─────────────────┼─────────┤ │ openjdk:25-ea (oracle 9.6) │ oracle │ 72 │ - │ └────────────────────────────┴────────┴─────────────────┴─────────┘ trivy image openjdk:21-ea Report Summary ┌────────────────────────────┬────────┬─────────────────┬─────────┐ │ Target │ Type │ Vulnerabilities │ Secrets │ ├────────────────────────────┼────────┼─────────────────┼─────────┤ │ openjdk:21-ea (oracle 8.8) │ oracle │ 132 │ - │ └────────────────────────────┴────────┴─────────────────┴─────────┘
  7. CVEs Are Exploited in 20% of Cases LOST MONEY LAWSUITS

    RUINED REPUTATION AUDIT FAILURE DATA BREACH REMOTE CODE EXECUTION VULNERABILITY $4.4M average breach cost
  8. In Dockerfile USER 1234:1234 Or: RUN groupadd -r myuser &&

    useradd -r -g myuser myuser USER myuser No Running Containers as Root KERNEL FLAW + ROOT IN CONTAINER = HOST AT RISK
  9. No excessive privileges No --privileged flag unless you absolutely need

    it: docker run --privileged Limit the privileges to those needed by the container: docker run --cap-drop all --cap-add <required-privilege> Prevent escalation of privileges at runtime: --security-opt no-new-privileges
  10. JRE at the final stage Docker multistage builds Minimalistic Linux

    JDK is for building and compiling JRE is for running Alpine (musl) Alpaquita (musl) Alpaquita (glibc) RHEL (Distroless UBI 10 Micro) Ubuntu Jammy Debian Slim Compressed size on Docker Hub 3.45MB 3.8MB 11.7MB 7.37MB 28.17MB 27.8MB Spoiler: Not all Linuxes are created equal
  11. FROM eclipse-temurin:25-jdk-alpine as builder WORKDIR /app COPY . /app/app RUN

    cd app && ./mvnw clean package FROM eclipse-temurin:25-jre-alpine WORKDIR /app RUN set -o errexit -o nounset \ && echo "Adding temurin user and group" \ && addgroup -Sg 1000 temurin \ && adduser -SG temurin -u 1000 temurin COPY --from=builder /app/app/target/app-*.jar app.jar USER temurin EXPOSE 8080 ENTRYPOINT ["java","-jar","/app/app.jar"]
  12. Scan Results for Our Demo ┌──────────────────────────────────────────────┬────────┬─────────────────┬─────────┐ │ Target │ Type

    │ Vulnerabilities │ Secrets │ ├──────────────────────────────────────────────┼────────┼─────────────────┼─────────┤ │ neurowatch-neurowatch:latest (alpine 3.23.3) │ alpine │ 3 │ - │ ├──────────────────────────────────────────────┼────────┼─────────────────┼─────────┤ │ app/app.jar │ jar │ 4 │ - │ └──────────────────────────────────────────────┴────────┴─────────────────┴─────────┘
  13. Don’t Live on CVSS Alone CVE Affected component Exploitability Patch

    availability External exposure Blast radius CVSS Triage CVE ID base / app dependency reachable / runtime path / attack preconditions yes / no internet -facing / internal single service / shared platform / lateral movement potential severity signal patch now / with next update / exception Output: A risk tier you can act on quickly
  14. We Found Dangerous CVEs! App CVEs Update the deps Update

    the base image Base CVEs But there’s a catch…
  15. Pulled a fresh base, scanning… eclipse-temurin:25-jre-alpine (alpine 3.23.3) Total: 3

    (UNKNOWN: 0, LOW: 0, MEDIUM: 1, HIGH: 1, CRITICAL: 1) ┌─────────┬────────────────┬──────────┬────────┬───────────────────┬───────────────┬ │ Library │ Vulnerability │ Severity │ Status │ Installed Version │ Fixed Version │ ├─────────┼────────────────┼──────────┼────────┼───────────────────┼───────────────┼ │ libpng │ CVE-2026-25646 │ HIGH │ fixed │ 1.6.54-r0 │ 1.6.55-r0 │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├─────────┼────────────────┼──────────┤ ├───────────────────┼───────────────┼ │ zlib │ CVE-2026-22184 │ CRITICAL │ │ 1.3.1-r2 │ 1.3.2-r0 │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├────────────────┼──────────┤ │ │ ├ │ │ CVE-2026-27171 │ MEDIUM │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─────────┴────────────────┴──────────┴────────┴───────────────────┴───────────────┴ The image has the same CVEs
  16. Shift security left Become an amateur OS/runtime maintainer Step 4.

    Pick a hardened base Goal: Delegate the dangerous package diffusion to pro deminers
  17. Hardened Images TRUSTED TRANSPARENT VERIFIABLE SLAs + CONSTANT patching You

    know what's in the image You know who built the image
  18. ASSET SUPPLIER NB: Choose the mission partner, not just the

    gear OS security, packaging, compliance Signatures, attestations, SBOMs Patch SLA Building from source EXPERTISE EVIDENCE REACTIVITY CONTROL
  19. YOUR MISSION SUPPORT TEAM ASSET 01 ASSET 02 ASSET 03

    Liberica JDK Runtime for any Java mission Alpaquita Linux Works in tight, hostile environments BellSoft Hardened Images Container armor SPRING APPROVED
  20. BELLSOFT HARDENED IMAGES IFU Pick libc: musl / glibc Pick

    release: Stream / LTS Contact your expert Request a patch if needed ADD-ONS UNLOCKED
  21. FROM bellsoft/hardened-liberica-runtime-container:jdk-25-glibc as builder WORKDIR /app COPY . /app/app RUN

    cd app && ./mvnw -Pproduction clean package FROM bellsoft/hardened-liberica-runtime-container:jre-25-glibc WORKDIR /app RUN set -o errexit -o nounset \ && echo "Adding liberica user and group" \ && addgroup -Sg 1000 liberica \ && adduser -SG liberica -u 1000 liberica \ COPY --from=builder /app/app/target/app-*.jar app.jar USER liberica EXPOSE 8080 ENTRYPOINT ["java","-jar","/app/app.jar"] IMAGE SIZE 219MB
  22. Let's scan it to make sure we are on the

    right way osv-scanner scan image bellsoft/hardened-liberica-runtime-container:jre-25-glibc Scanning image "bellsoft/hardened-liberica-runtime-container:jre-25-glibc" Starting filesystem walk for root: End status: 150 dirs visited, 854 inodes visited, 202 Extract calls, 9.993542ms elapsed, 9.993ms wall time No issues found ZERO CVEs
  23. Provenance = verifiable supply chain evidence for: Base image authenticity

    App contents Build origin Did this really come from the expected publisher? What dependencies and artifacts are inside? Who and what built this image?
  24. Verify base image signature: $ cosign verify \ --key cosign.pub

    \ <image-uri>@sha256:<digest> Verify attestation and get the SBOM: $ IMG='docker.io/bellsoft/hardened-base:glibc' cosign verify-attestation \ --key ~/keys/cosign-bellsoft.pub \ --type cyclonedx \ $IMG | jq -r '.payload' | base64 -d | jq '.predicate' If the foundation is fake, everything built on it is compromised!
  25. Generate an SBOM for Your App Image Produce an SBOM

    for the application Store it together with the base image SBOM 💡Separation of concerns: OS packages VS application dependencies Am I affected? Is this CVE in base image or app deps? What changed between builds?
  26. Scan SBOMs SBOM scan is fast and reproducible Works well

    for rescans Security checks are tied to a specific image digest/build We have SBOMs = we scan what we actually built
  27. Scan application SBOM: osv-scanner -L target/app-sbom.cdx.json --output app-scan-results.json Scan base

    image SBOM: osv-scanner -L target/app-sbom.cdx.json --output base-scan-results.json Classify risks as discussed in Step 2
  28. MISSION DEBRIEF MISSION ACCOMPLISHED CVEs Image size Base image Evidence

    46 1GB standard none 0 219MB hardened SBOMs CVE-ridden bloated image with unclear ownership to fortified manageable asset.