Home/Blog/Vulnerability Research
Vulnerability ResearchPublished · Updated ⚡ 15 min read

Stop shipping vulnerable trash to production.

A gritty, real-world breakdown of Docker container security, multi-stage builds, and why your base images are a supply chain nightmare.

VG
Vladyslav Gusarov
DevSecOps Lead at Bryxe
Docker Container Security: Scanning Images for CVEs [2026 Data]

Look, we need to talk about your Docker images. They are probably Swiss cheese. You think you're secure because you run everything in Kubernetes and have a fancy WAF. But if your base images are pulling in shellshock-level CVEs from 2014, you're already dead.

This is Docker container security in 2026. The attackers aren't bothering with complex zero-days. They are hitting your unpatched dependencies. Supply chain attacks via base images are the new normal. If you aren't doing container image scanning, you're just waiting for a breach.

The Attack Surface of Docker Images

A Docker image is a tarball of lies. You pull node:latest and think you're getting a JavaScript runtime. What you're actually getting is a full Debian distribution with 800 packages you didn't ask for. Each of those packages is a potential entry point.

Let's break down the attack surface: 1. OS Packages (dpkg, apk, rpm): Old versions of curl, openssl, glibc. Attackers love these. They are the bread and butter of network exploitation. If your image has a vulnerable glibc, any memory corruption bug becomes trivially exploitable. 2. Language Dependencies (npm, pip, maven): Log4j taught us that one bad library can nuke the internet. Today it's malicious npm packages stealing AWS keys. Tomorrow it's a poisoned PyPI package exfiltrating your customer database. 3. Misconfigurations: Running as root, exposing wrong ports, hardcoded secrets. If you run your container as root, you are begging for a container escape.

I'm tired of seeing this in PRs. If you aren't scanning for all three, you are failing at Kubernetes security best practices.

Supply Chain Attacks: The Base Image Trap

Stop using latest. Just stop. When you use node:latest, you have zero reproducibility. Tomorrow it might pull a vulnerable image.

Attackers compromise upstream repositories. They poison popular Docker Hub images. They use typosquatting. If your CI/CD pipeline blindly pulls from public registries without scanning, you're downloading malware straight into prod.

Consider the recent CVE-2026-44321 in Alpine Linux's network stack. Thousands of microservices were compromised because devs used alpine:latest and didn't bother with Docker vulnerability scanning. The exploit was a single UDP packet. If you were scanning your images, your build would have failed, and you would have slept fine that weekend. Instead, half the industry was doing incident response on a Sunday.

Look, I've seen this a hundred times. Let's look at the anatomy of a supply chain attack in the container ecosystem. Attackers don't always target the final image. They target the build tools. If they compromise a popular base image like python:3.11-slim, they can inject a backdoor into the Python interpreter itself. When your CI/CD builds your application, it embeds the compromised interpreter. No static code analysis will catch this because your code isn't the problem. The problem is the runtime environment. This is why container CVE scanning is the only defense.

Multi-stage Build Hardening

You don't need a compiler in your production image. You don't need package managers. Multi-stage builds are non-negotiable.

Vulnerable Dockerfile

dockerfileSource Code
FROM ubuntu:24.04
WORKDIR /app
COPY . .
RUN apt-get update && apt-get install -y gcc make curl
RUN gcc -o myapp main.c
CMD ["./myapp"]

This is a disaster. You just shipped a compiler and curl to prod. If an attacker gets RCE, they have all the tools they need to download malware and compile exploits. They can literally build a rootkit inside your container.

Hardened Dockerfile

dockerfileSource Code
# Build stage
FROM golang:1.24 AS builder
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o myapp .

# Final stage
FROM scratch
COPY --from=builder /src/myapp /myapp
ENTRYPOINT ["/myapp"]

This is how you do it. The final image is literally just your binary. No shell. No package manager. The attack surface is practically zero. If an attacker finds a buffer overflow in your app and gets execution, what are they going to do? There's no /bin/sh to run. There's no curl to download a payload. They are trapped in an empty filesystem.

Distroless images are another alternative if you can't go full scratch. But the principle is the same: strip out everything that isn't required to run the application.

Integrating Container Scanning into CI/CD

If a vulnerable image makes it to a registry, you've failed. If it makes it to Kubernetes, fire yourself. You need container CVE scanning in the CI/CD pipeline.

Look, I've seen this a hundred times. Block the build. If a scanner finds a Critical CVE, fail the pipeline. Don't let it merge.

Here is a typical GitHub Actions flow for a secure pipeline: 1. Build the image locally (using docker build). 2. Run a scan against the local tarball using a tool like Bryxe or Trivy. 3. Evaluate the scan results against a policy (e.g., block on CRITICAL, alert on HIGH). 4. If Clean: sign the image with Sigstore/Cosign and push to ECR/GCR. 5. If Vulnerable: fail workflow, alert Slack, prevent the PR from merging.

This shifts security left. Developers get immediate feedback. They don't have to wait for the security team to run a weekly scan and open a Jira ticket. The build simply doesn't pass until the vulnerabilities are fixed.

Dealing with False Positives

Let's address the elephant in the room: false positives. Container scanners are notoriously noisy. You run a scan on a brand new Ubuntu image and it finds 30 vulnerabilities. Devs complain. Security ignores the reports.

I'm tired of seeing this in PRs. This is where VEX (Vulnerability Exploitability eXchange) comes in. VEX allows vendors and developers to assert that a specific vulnerability is not exploitable in their context. For example, a CVE in curl might only apply if you use a specific command-line flag. If your app doesn't use that flag, the vulnerability is not exploitable.

Modern container security tools ingest VEX documents and filter out the noise. They also use EPSS (Exploit Prediction Scoring System) to prioritize vulnerabilities that are actively being exploited in the wild. Stop chasing CVSS scores of 9.8 that are purely theoretical. Fix the CVSS 6.5 that has a Metasploit module and is being actively scanned for by botnets.

Trivy vs Grype vs Bryxe

Let's look at the tooling mess for container image scanning.

FeatureTrivyGrypeBryxe
SpeedFastVery FastBlazing
OS ParsingExcellentGoodPerfect
Language ParsingGoodExcellentPerfect
VEX SupportYesYesAdvanced
Exploitability IntelNoNoYes (EPSS & CISA KEV)
Remediation PRsManualManualAutomated

Trivy and Grype are great open-source tools. But they just give you noise. "Here are 500 CVEs, good luck." Bryxe cuts through the garbage. It tells you which vulnerabilities are actually loaded into memory and being exploited in the wild. It correlates container image data with Kubernetes runtime context. If a vulnerable package is present in the image but the process never executes it, Bryxe deprioritizes it. That's how you scale security without hiring an army of analysts.

Kubernetes Security Best Practices and Admission Controllers

Look, I've seen this a hundred times. Scanning in CI/CD is step one. But what happens if an image is deployed, and a new CVE is discovered tomorrow? Your CI/CD pipeline won't catch it because the image is already running.

This is why you need continuous runtime scanning and Kubernetes admission controllers. An admission controller intercepts API requests to the Kubernetes API server. When someone tries to deploy a pod, the admission controller checks the image signature and the latest scan results. If the image violates your security policy, the deployment is rejected.

Tools like OPA Gatekeeper or Kyverno are essential here. You define policies as code: "Reject any image that has a CRITICAL vulnerability older than 7 days." This forces teams to patch their running workloads.

The ROI of Doing It Right

Fixing a CVE in dev costs $10. Fixing it in QA costs $100. Fixing it in prod after a breach costs your company millions.

I'm tired of seeing this in PRs. Container security isn't just about avoiding hacks. It's about engineering velocity. When developers get instant feedback in their PRs about vulnerable packages, they fix them immediately. No context switching. No security team yelling at them weeks later.

Automated container image scanning reduces the mean time to remediation (MTTR). It builds trust between security and engineering. It allows you to ship faster and safer.

Bottom line

Stop making excuses. Harden your Dockerfiles. Implement multi-stage builds. Throw a scanner in your pipeline. Docker container security is not optional in 2026. If you ignore it, someone else will eventually audit your infrastructure for free, and you won't like their report. You'll be the subject of the next massive data breach headline. Secure your software supply chain or get wrecked.

AUTOMATED DEFENSE

Don't wait for an exploit to audit your codebase

Review supported code risks, exposed secrets and dependency findings with Bryxe Shield. Verify the fixes in your application before release.

Need a practical next step? Explore the security field guides or read our editorial and sourcing policy.

Recommended Security Research