Minimal Container Images

Minimal Container Images

A production image ships a compiler, a package manager, and a shell, turning a small application flaw into a working toolkit. Perform the pivot, then cut the runtime down to a minimal stage with none of it.

What Is Minimal Container Images?

Every tool you ship in a production image is a tool an attacker inherits. A runtime image carrying a package manager, a compiler, a shell, and network utilities turns a limited application flaw into a working toolkit, because the attacker no longer has to bring anything with them. This exercise covers that escalation: watch an attacker pivot using the image's own contents, then cut the runtime down to a minimal stage with no shell and no build tooling.

What You'll Learn in Minimal Container Images

Minimal Container Images — Training Steps

  1. A foothold in checkout

    Bob does not start with a shell. The checkout service builds PDF shipping labels and shells out to do it, and one field in that request is not sanitised. He injects a probe to confirm he can run a command, and to see who and where he is.

  2. Everything the image ships

    Bob has one-command-at-a-time execution as the app, but no shell yet. That is usually where an attacker stalls, unless the container hands him a toolkit. Before doing anything loud, he checks what is already installed.

  3. Curl the cloud credentials

    The container runs in the cloud, and every cloud instance exposes a metadata service on a fixed internal address that hands out the machine's temporary role credentials. Reaching it needs an HTTP client. The image shipped one.

  4. How one command became a breach

    Bob's access to the app was tightly limited.

  5. A shell in a runtime container

    Skelwyn runs endpoint detection on its container hosts. It does not know what each container is for; it reports behavior that does not fit a runtime.

  6. Confirm what shipped

    Alice reproduces what the attacker found: she asks the running container which of those tools it actually contains.

  7. A 412MB runtime

    The toolkit is not free. It is weight, and it is attack surface. Alice checks the size of the image the service actually runs.

  8. Where the toolkit gets in

    The image is built from one Dockerfile. Alice opens it to see why a runtime container ends up carrying a compiler.

  9. One stage, everything ships

    The image is built and run in a single stage, so whatever the build needs, the runtime also carries.

  10. Split build from runtime

    The fix is a multi-stage build: keep the full image and its toolchain as a build stage that compiles the app, then copy only the finished app and its dependencies into a distroless runtime image that has no shell, no package manager, and no compiler.