Your Container Image Contains a Package Manager an Attacker Can Use

Key takeaway: Every binary in an image is a tool available to an attacker who achieves execution. Removing what the application does not need eliminates capability rather than merely patching it.
What a Default Image Provides
Building on a general-purpose base image produces a container containing a shell, curl or wget, a package manager, ps and netstat, and several hundred libraries.
An attacker who gains execution inside that container has a complete working environment. They can download tooling, install packages, enumerate the network and pivot — all using software you shipped.
Removing those binaries does not fix the vulnerability that allowed execution. It substantially reduces what execution is worth.
Comparing Base Images
| Base | Approximate size | Contents | CVE surface |
|---|---|---|---|
| Full distribution | 700 MB+ | Everything | Large |
| Slim variant | 80–120 MB | Reduced | Moderate |
| Alpine | 5–15 MB | Busybox, apk | Small |
| Distroless | 2–20 MB | Runtime only, no shell | Very small |
| Static scratch | Binary only | Nothing else | Minimal |
Distroless images contain the language runtime and its dependencies with no shell, no package manager and no utilities. For compiled languages, a static binary on scratch goes further — the image contains one file.
The vulnerability count difference is dramatic and mostly reflects removed packages rather than fixed ones. A scanner reporting two hundred findings on a full base image and three on distroless is describing the same application; the difference is everything that was not needed.
The Operational Objection
The standard resistance is that debugging requires a shell. This is a real concern with a good answer.
Ephemeral debug containers attach a separate image containing your tooling to a running pod’s namespaces, giving full diagnostic capability without that tooling being resident in the production image. The debug container exists for the duration of the investigation and then disappears.
That arrangement is strictly better than a permanent shell, because the capability is available on demand to authorised operators rather than continuously to anyone who achieves execution.
Comprehensive logging and metrics reduce the need for interactive debugging in the first place. Teams that reach for a shell frequently are usually compensating for insufficient instrumentation.
Other Hardening That Matters
Run as a non-root user with an explicit numeric UID, and set the filesystem to read-only with writable volumes only where genuinely required. Drop all Linux capabilities and add back only what the process needs — most applications need none.
Multi-stage builds are the mechanism that makes minimal images practical. Compile with a full toolchain in the build stage, copy only the resulting artefact into a minimal runtime stage. Build dependencies never reach production.
Pin base images by digest rather than tag. A tag is mutable, so :3.12 today and tomorrow may be different images, which defeats reproducibility.
The Bottom Line
Use distroless or static base images with multi-stage builds, run as non-root with a read-only filesystem and no capabilities, and pin by digest. Handle debugging with ephemeral containers rather than by shipping a shell.



