Skip to main content

Chainguard and Wolfi Cross 2,000 Zero-CVE Images: Should a Self-Hosted PaaS Default to Them?

9 min readDora NodaDora Noda
Share
On this page

A standard Debian-based Docker Hub image ships with roughly 280 known CVEs before you've written a line of application code. Chainguard's equivalent image ships with zero. As of February 2026, Chainguard has produced more than 500 million unique container build manifests across a catalog of 2,000+ image families, all rebuilt from Wolfi — a Linux "undistro" purpose-built to have almost nothing in it. For a git-push PaaS whose build pipeline currently hands a tenant's Dockerfile whatever base image the tenant happened to type in, that gap raises a concrete question: should the platform's own buildpack and Dockerfile output default to a Wolfi-based image instead of leaving the base image entirely up to chance?

The gap, in numbers

Before getting into architecture, here's what actually changes when a container stops being built on a general-purpose distro:

Standard Debian-based imageChainguard (Wolfi)Google Distroless
Typical known CVEs (base layer)~28007 high-severity (Python image, glibc/OpenSSL layer)
Patch latency after upstream fixWhenever the distro maintainer re-cuts the imageHoursWhenever the project re-cuts the image
Runtime shell / package managerYesNoNo
SBOM + signature shipped by defaultRareEvery image (Cosign-signed)No

Three DACH-region teams — a bank subsidiary running 230 microservices, an insurance platform provider, and an industrial manufacturer — migrated from standard distro bases to Distroless/Wolfi/Chainguard images over a 12-month window and reported 60-80% reductions in build time, CVE surface, and egress cost. That's not one favorable case; it's three different profiles landing in the same range, which is the kind of result worth taking seriously rather than one cherry-picked benchmark.

Those numbers are the deliverable. Everything below is what they actually mean for a platform that owns its own Cluster API fleet instead of renting someone else's.

What Wolfi actually is (and the Alpine question everyone asks first)

Wolfi isn't a smaller Debian. Chainguard calls it an "undistro" for a specific reason: a normal distribution ships hundreds of interdependent packages designed for general-purpose computing, where a security fix to OpenSSL might require testing against a shell, a package manager, cron, and a dozen other things installed alongside it. Wolfi packages are granular and independently versioned instead — the repository currently lists over 15,000 distinct packages, but a Wolfi-based image only contains the ones your application actually needs. No shell, no package manager, no init system in the runtime image, because none of those are part of running your app.

The first question any Node or Python developer asks here is "isn't this just Alpine?" It isn't, and the difference matters more than the marketing copy suggests. Alpine is musl-libc, and musl breaks native addons that assume glibc — bcrypt, sharp, and anything else that shells out to node-gyp has a long history of silently misbehaving or failing to build on Alpine, which is why teams that tried "just switch the base image to Alpine" for the CVE win often ended up debugging a segfault instead. Wolfi is deliberately glibc-based. It gets Alpine's minimalism without inheriting Alpine's compatibility tax on compiled dependencies — which is the actual reason Wolfi displaced Alpine as Chainguard's foundation rather than building on the already-popular musl base.

What this changes for a Cluster API fleet specifically

Three concrete things change on a self-hosted, multi-tenant fleet once tenant images are built on a minimal base instead of an arbitrary one:

Image-pull time on nodes. Every new Machine a Cluster API-managed fleet provisions, and every pod rescheduled after a node drain, pulls the images it needs before it can serve traffic. A Debian-slim-based image with a full apt package set pulls measurably slower than a Wolfi-based equivalent with a fraction of the layers — the DACH case study's build-time reduction is largely this same effect showing up earlier in the pipeline. On a bin-packed fleet where pods reschedule constantly, pull time isn't a one-time cost; it's paid on every reschedule.

Attack surface at the image layer, not the node layer. We've written before about Talos Linux dropping SSH and a shell at the node OS level. Wolfi does the analogous thing one layer up, inside the container: if an application has a remote code execution bug, the blast radius of "what can the attacker do once they're in the container" shrinks to whatever's actually in a Wolfi-based runtime image — which is close to nothing. No shell to spawn a reverse connection from, no package manager to pull in more tools, no coreutils beyond what the app itself needs. The two hardening layers are complementary, not redundant: Talos protects the node a tenant's container runs on; Wolfi protects what a tenant's own container can do once something inside it is compromised.

CVE-scanning noise. Every self-hosted platform running a vulnerability scanner against tenant images eventually has to decide what to do with hundreds of findings per image, most of them in a base layer the tenant never touched and can't easily fix. A near-zero-CVE base collapses that triage queue from "scroll past 280 findings to find the ones that matter" to "the findings that show up are almost always in the application layer, where they're actually actionable."

The part "defaulting" glosses over: this changes other people's images

Here's the catch the case study above doesn't surface, because it describes teams choosing this for their own applications — not a platform silently rewriting a base image out from under a tenant. A self-hosted PaaS that defaults its buildpack or Dockerfile output to a Wolfi base is changing what tenants get without them typing anything different, and that has real failure modes:

  • A tenant's Dockerfile that shells into the running container for a health check or a debug session breaks, because there's no shell.
  • A tenant's apt-get install in a multi-stage build step, or an entrypoint script that assumes bash exists, breaks the same way.
  • A native dependency with a package that hasn't been ported to Wolfi's repository yet has no drop-in equivalent — the package set is smaller by design, and "smaller" occasionally means "not there."

None of these are reasons to skip the default — they're reasons the rollout has to be additive, not retroactive. The safe version of "default to Wolfi" is: new repos and buildpack-detected builds get a Wolfi-based image from day one, existing tenant images are left alone until a tenant opts into a rebuild, and any Dockerfile that pins its own FROM line is respected as-is. That's a materially different claim than silently swapping the base image under a workload someone already has running in production.

Free Wolfi vs. paid Chainguard — the build-vs-buy decision

Once a platform decides to default new builds to a minimal base, the next question is which minimal base: the free Wolfi package repository, built and patched yourself, or Chainguard's paid catalog, which is already built and patched for you.

Building on Wolfi directly means using Chainguard's own open-source tooling — apko to assemble an image from Wolfi packages declaratively, melange to build a Wolfi package from source when one doesn't already exist — and owning the pipeline that rebuilds and rescans images when an upstream CVE lands. Nothing here costs money. What it costs is engineer time: someone has to run that rebuild pipeline, watch for new advisories, and be the one who patches within hours instead of whenever a scheduled job happens to run next. There's no SLA, because there's no vendor — the guarantee is only as good as the automation your own team builds and maintains.

Subscribing to Chainguard's catalog buys the same Wolfi foundation, already assembled into 2,000+ maintained image families, with Chainguard's own factory rebuilding and re-signing within hours of an upstream fix — the same factory that's produced 500 million build manifests, which is the throughput evidence that "hours, not days" is a track record and not a marketing claim. Chainguard doesn't publish a flat per-image-family price; its catalog licensing scales with the size of the engineering org consuming it, quoted through sales rather than a public rate card. The honest tradeoff isn't a dollar figure this piece can respectably hand you — it's build-vs-buy in the plainest sense: pay for someone else's patch pipeline and get an SLA, or run your own pipeline on free packages and own the risk that "hours" quietly becomes "whenever we get to it."

The verdict for a git-push platform's build path

For a platform whose entire pitch is owning the infrastructure rather than renting someone else's, the free-Wolfi path is the more consistent default: apko and melange on top of the existing Cluster API-managed build pipeline, with Chainguard's catalog as the pragmatic upgrade for a team that would rather pay for an hours-not-days patch SLA than staff it themselves. Either way, the default worth shipping is narrower than "rebase everything on Wolfi" — it's "new buildpack and Dockerfile-less builds land on a minimal base from day one, existing tenants opt in, and anyone who pins their own FROM line keeps exactly what they asked for."

Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. Star the repo on GitHub or deploy your first app today.

Sources

Related articles

Run this on infrastructure you own

bex is the open-source, AI-native Render alternative — push a git repo and get a running HTTPS service on your own machines.

Get started with bex