How to Eliminate 1,400 CVEs from Your Container Images

NanoClaw eliminated 1,400+ container CVEs by switching to minimal base images and multi-stage builds.
NanoClaw's case study highlights a common yet underestimated container security problem: the vast majority of CVEs come not from application code, but from redundant system packages in base images and bloated dependencies. The two core remediation strategies are replacing general-purpose distro images with minimal alternatives like Distroless, Alpine, or Chainguard, and adopting multi-stage builds to fully isolate the build toolchain from the runtime environment. While fewer CVEs doesn't directly translate to proportionally lower real-world risk, it significantly reduces compliance complexity and security team alert fatigue — embodying the "shift-left security" principle of baking security decisions into the build stage rather than relying on after-the-fact patching.
Introduction: The Hidden Security Burden of Containers
In modern cloud-native application development and deployment, container images have become the fundamental unit of software delivery. Yet as image layers accumulate and dependencies pile up, security vulnerabilities (CVEs, Common Vulnerabilities and Exposures) quietly build up alongside them. A case study recently shared by the NanoClaw team caught the attention of the Hacker News community: they successfully eliminated 1,400 CVE vulnerabilities from their container images.
That number is jarring at first glance — how could a single project's container image accumulate over a thousand known vulnerabilities? But for engineers familiar with container supply chain security, it's not unusual at all. It exposes a widely overlooked reality: most container vulnerabilities don't come from application code itself, but from base images and transitive dependencies.

Where Do 1,400 CVEs Come From: A Deep Dive into Vulnerability Sources
Base Images Are the Primary Source of Vulnerabilities
When developers use base images like FROM ubuntu:latest or FROM node:18, they're not just pulling in the runtime their application needs — they're also importing an entire OS distribution's worth of system packages. Each of those packages may contain known or unknown security vulnerabilities.
A typical full Linux distribution image might include:
- Package management tools (apt, yum, etc.)
- Shell environments and various system utilities (bash, curl, wget)
- Compiler toolchains and debugging tools
- A large number of system libraries that are never needed at runtime
These components are often entirely unnecessary for the application to actually run, yet their presence dramatically expands the attack surface. When vulnerability scanners (such as Trivy, Grype, or Snyk) scan an image, these redundant components account for the overwhelming majority of CVE findings.
The Cascading Effect of Dependency Bloat
Beyond base images, dependency bloat at the application layer is another major contributor to CVE accumulation. A Node.js or Python project might directly depend on dozens of packages, each of which pulls in hundreds of transitive dependencies. Any outdated component anywhere in that graph can introduce new CVEs.
What makes this even trickier is that many of these vulnerabilities are effectively "unexploitable" — the relevant code paths are never triggered at runtime. But vulnerability scanners can't distinguish this; they flag everything as a risk, generating massive amounts of alert noise that leaves security teams constantly playing catch-up.
Core Strategies for Eliminating CVEs
Use Minimal Base Images
The most impactful strategy in the NanoClaw case was migrating from bloated, general-purpose distribution images to minimal or distroless images. The core philosophy here is simple: include only what the application actually needs to run, and strip out everything else.
Common minimal image options include:
- Distroless images: Maintained by Google, these contain only the application and its runtime dependencies — no shell, no package manager
- Alpine Linux: A minimal distribution based on musl libc, a fraction of the size of traditional distros
- Chainguard Images / Wolfi: Purpose-built for supply chain security, targeting near-zero CVEs
- Scratch images: A completely empty base image, suitable for statically compiled binaries
Switching to one of these minimal alternatives can eliminate hundreds or even thousands of system-level CVEs in a single move. This is the fundamental reason NanoClaw was able to achieve such a dramatic reduction.
Use Multi-Stage Builds to Separate Build and Runtime Environments
Another highly effective practice is multi-stage builds. Developers can use a full-featured image with a complete toolchain during the build stage to compile the application, then copy only the final artifacts into a clean, minimal runtime image.
This way, compilers, build tools, temporary files, and other build-time dependencies never make it into the final delivered image — reducing both image size and the runtime attack surface significantly.
Deeper Security Lessons
Security Should Shift Left to the Build Stage
The most important takeaway from this case is that container security shouldn't just be a post-deployment scan-and-patch exercise — it should proactively reduce the attack surface at image build time. Rather than manually triaging thousands of alerts after the fact, the better approach is to start with a leaner, more secure foundation.
This aligns with the industry's growing emphasis on "shift-left security" — bringing security considerations into the development process as early as possible, rather than bolting them on as an afterthought.
CVE Count ≠ Real Risk
It's worth emphasizing that eliminating 1,400 CVEs doesn't mean the application previously had 1,400 exploitable attack vectors. A significant portion of those were unreachable code paths or low-severity findings. Even so, reducing CVE counts has real, practical value:
- Simplifies compliance audits: Many industry standards require images to pass vulnerability scans
- Reduces alert fatigue for security teams: Makes it easier to spot genuinely high-severity issues
- Shrinks the potential attack surface: Even if a vulnerability isn't exploitable today, future code changes could activate it
Conclusion
NanoClaw's effort to eliminate 1,400 CVEs is, at its core, a vivid lesson in container supply chain security. It reminds us that the security of a container image is largely determined by what you choose to include, not what you patch after the fact.
For any team building cloud-native applications, seemingly basic engineering practices — choosing minimal base images, adopting multi-stage builds, integrating security checks into the CI/CD pipeline — often deliver the most significant security gains. In an era of increasingly frequent software supply chain attacks, doing less is sometimes more important than doing more.
Related articles

Vercel AI SDK Releases @ai-sdk/tui 1.0.100 Patch Update
Vercel AI SDK releases @ai-sdk/tui 1.0.100 patch update, syncing the core ai dependency to 7.0.99. Learn about this update and Vercel AI SDK's modular versioning strategy.

@ai-sdk/workflow 2.0.30 Released: Dependency Sync with AI SDK Core
Vercel AI SDK releases @ai-sdk/workflow 2.0.30, a patch update syncing the dependency to ai@7.0.99. Learn what changed and how developers should respond.

Claude's 200,000-Character System Prompt Leaked: An In-Depth Analysis
An in-depth analysis of Claude's leaked ~200,000-character system prompt, covering safety constraints, memory management, copyright compliance, and multi-model routing architecture.