Build Image on Host (T1612) is a Stealth technique on the Containers platform. The adversary builds a container image directly on a host to avoid defenses that watch for malicious images being pulled from a public registry.
It exploits a blind spot. Many controls inspect images as they arrive. An image created on the machine never arrives.
How attackers use it
MITRE describes a remote build request sent to the Docker API that includes a Dockerfile. The Dockerfile pulls a plain base image such as alpine from a public or local registry and builds a custom image on top. That custom image can include malware downloaded from the adversary's command and control server. The adversary then uses Deploy Container (T1610) to run it.
The reasoning is about reputation. If the base image comes from a public registry, defenses will probably not flag it, since it is a vanilla image. If it is already in a local registry, the pull looks even less suspicious because the image is already in the environment. The malicious part is added at build time, after the point where most scanning happens.
How to detect it
MITRE's analytic watches for container image build activity directly on the host through the Docker or Kubernetes APIs. It lists these signals:
- Docker build requests that you did not expect.
- Dockerfile instructions that download code from unknown IP addresses.
- Creation of a new image followed quickly by deployment.
- An unexpected image creation event correlated with outbound network connections to non standard or untrusted destinations.
For most teams the pivotal question is where builds are supposed to happen. If images are built only in CI and pushed to a registry, then any build request arriving at a production host's Docker API is suspicious by definition. That is a clean, low-noise rule.
How to reduce the risk
MITRE lists these mitigations:
- Limit access to the Docker API. Use local Unix sockets or SSH for remote access, and require TLS. Disable unauthenticated access to the Docker API on port 2375, and use TLS on port 2376 instead.
- Do not run containers as root by default. In Kubernetes, use Pod Security Standards to prevent privileged containers.
- Segment the network. Deny direct remote access to internal systems with proxies, gateways and firewalls.
- Audit deployed images. Check images running in the environment for malicious components, not only the ones that came through the registry.
A related control is to gate production on provenance. If only images signed by your pipeline may run, an image built on a host will not qualify. The demo below shows a production gate.
Check your own environment
Read-only checks (Docker on Linux):
# Is the Docker API listening on a TCP port? 2375 is plaintext, 2376 is TLS
ss -ltn | grep -E ':2375|:2376'
# Images present on this host, with creation time and size
docker images --format '{{.Repository}}:{{.Tag}} {{.ID}} {{.CreatedSince}}'
# Show how an image was built, layer by layer
docker history IMAGE_NAME
Replace IMAGE_NAME with a real image. Then review:
- Do any production hosts hold images that your CI pipeline never produced?
- Is port 2375 closed everywhere?
- Do you log Docker API requests, including build calls?
- Can your deployment path reject an image that has no pipeline provenance?
Try it yourself
Click through it at your own pace, or open it full screen.
Quick check
Why does building on the host evade registry-focused defenses?
The base image is a plain one from a public or local registry, which looks clean. The malicious content is added during the build, after the point where pulls are inspected.
Which port does MITRE say to avoid for the Docker API?
2375, which is unauthenticated and unencrypted. Use TLS on 2376 instead, or local Unix sockets or SSH.