← All field notes
container supply chainregistry credential theftfor developers

A poisoned base image: when cleaning your registry is not enough

Stolen registry credentials repoint a popular tag to a poisoned image, and downstream builds inherit the implant. The containment step internal-only thinking forgets is the notification.

A published base image is a dependency for everyone who builds on it. When the credential that publishes it is stolen, the harm flows downstream automatically.

How the attack works

An attacker steals a Docker Hub access token for a published base image repository. Using that token from a location and client never seen in releases, they repoint a widely used tag, the stable tag, to a new image layer set with an implant added on top of the legitimate base, entirely off the signed release pipeline. Every downstream pipeline that pulls the base image by that mutable tag inherits the implant on its next build, bakes it into its own images, and those containers then beacon out to an external endpoint. In ATT&CK terms this is T1195, Supply Chain Compromise, paired with T1525, Implant Internal Image.

Why it works

Downstream pipelines pulled the base image by a mutable tag and trusted whatever it pointed to. A tag is not a verifiable identity. Repointing it silently changes what everyone downstream receives, with no signature check to catch the swap.

How to fix it

This is a supply chain incident, so the harm has already left your boundary. Rotate the registry token, not just a human password, and remove or repoint the poisoned tag to a known clean signed image. The step internal only thinking forgets is mandatory: notify downstream consumers with the specific poisoned digest so they stop pulling and rebuild from a clean base. The durable fix makes a silent swap fail closed: pin base images by immutable digest, require image signing and verify signatures at pull or admission time, and scan in the pipeline so an unsigned or mutated image is rejected. Use the registry account activity, tag history, and pull logs to scope exactly who pulled the poisoned digest.

Practice it

We built this as a GraphLattice Range scenario so developers can rehearse the rotate, clean, and notify sequence and the digest pinning that stops a tag swap cold.