Docker patches command execution via BuildKit’s Git checkout and five other build flaws
On July 16 2026 Docker Engine 29.6.2 fixed five BuildKit vulnerabilities, including CVE-2026-15793 which can execute commands on the host during a malicious Git checkout, and CVE-2026-17106 was fixed in 29.7.0. Pipelines that build from untrusted sources should update Engine, Buildx and BuildKit now.
July 16 2026. Docker ships Engine 29.6.2 and fixes five vulnerabilities in BuildKit, its image build engine. July 30 2026. 29.7.0 follows with CVE-2026-17106, an archive-extraction path traversal. August 5 2026. 29.7.2 closes the wave with regression fixes. In three weeks the docker build attack surface closed over six flaws, one of them command execution reachable from a mere Git source.
The flaw that matters: a command injected through Git checkout
CVE-2026-15793 is the most serious of the batch. It lives in BuildKit: a custom frontend or a client using the raw low-level API can set git.checkoutbundle=true when checking out a Git source. If that source is malicious, the mechanism leads to a crafted command invocation on the host.
Rated CWE-88, it scores CVSS 4.0 7.3 with a high severity. The NVD vector is unambiguous: attack complexity is low, scope is limited to the victim, but confidentiality, integrity and availability impact are all high. In plain terms, the flaw needs no special privilege — only a build performed against a Git source the attacker controls.
The operational nuance matters. The trigger is not an innocent Dockerfile: it needs a frontend or client that explicitly enables the bundle checkout optimisation. But that optimisation is exactly what many CI/CD pipelines enable to speed up clones. The line between “edge case” and “real pipeline” is thinner than it looks.
Why “frontend” and the low-level API matter
To gauge the reach of these flaws, you have to understand BuildKit’s architecture. The buildkitd daemon separates two worlds: the frontend, which translates a Dockerfile into low-level instructions, and the solver, which executes them through workers. Between the two flows the low-level LLB API, the internal language most developers never see.
The five flaws fixed in July live exactly on that boundary. They do not assume a poisoned Dockerfile in the classic sense; they assume a client or frontend able to talk directly to buildkitd. That is precisely what advanced pipelines do: a runner invoking a custom frontend, a remote client sending LLB instructions to a shared daemon, or a pooled build service. The more industrialized the tooling, the more reachable this surface really is.
Four more BuildKit flaws, all high severity
29.6.2 does not patch one flaw; it ships five, all rated high, and their variety says something about the maturity of the target:
- CVE-2026-15792 — CVSS 7.5: a malicious client or frontend crafts a request that makes the BuildKit daemon panic. An unauthenticated network denial of service.
- CVE-2026-15791 — CVSS 7.5: a forged message in the low-level API deletes the contents of
/tmp. An operation meant to stay inside the build container rootfs escapes into the host’s real temp directory. - CVE-2026-15789 — CVSS 7.5: a forged upload request pushes files out of the BuildKit-controlled state directory.
- CVE-2026-15788 — CVSS 7.5: on WCOW (Windows) workers, the
source=cache selector fails to detect NTFS junctions inside the cache root; a build authored by an untrusted user reads arbitrary host files.
Three of the five map to CWE-22 (path traversal) or CWE-59 (uncontrolled link). The pattern is constant: the boundary between the build world and the host world is more porous than operators assume.
CVE-2026-17106: the archive extraction that escapes
CVE-2026-17106, fixed in Engine 29.7.0, cuts even wider. It lives in moby/go-archive, the decompression library shared across the Moby ecosystem. Its routines — Unpack, UnpackLayer, Untar — decide where each archive entry lands using lexical string checks, then let the OS resolve the path. Links introduced by the archive can therefore be followed outside the destination directory.
The consequence: an attacker who controls the contents of an archive — an image, a build context, a layer — can create or overwrite files at arbitrary paths writable by the extracting process. NVD rates it CVSS 4.0 7.1, high, published August 18 2026. It hits docker build as much as the docker pull of a compromised image.
What the sequence reveals about build as an attack surface
These six flaws share one lesson. For years the build pipeline was treated as an infrastructure detail, watched less closely than the production it feeds. Yet the build is where untrusted code — dependencies, Git sources, base images — meets a privileged daemon on the host.
The July cluster is not a coincidence. BuildKit became Docker’s default engine and the foundation of most build platforms, from GitHub Actions to self-hosted runners. What gets fixed there propagates everywhere, and so does what stays vulnerable. A CI runner building from public forks is, structurally, a forward outpost of the supply chain.
The version of the fix matters. The fixes live in BuildKit itself; Docker Engine 29.6.2 bundles them, but a standalone buildkitd daemon, a Docker Buildx embedded in a runner, or an outdated Docker Desktop still carries the flaw. Checking the Engine version alone is not enough.
The 2026 context sharpens the lesson. The tj-actions incident, which leaked CI/CD secrets across tens of thousands of repositories, and the Actions security roadmap GitHub published afterward, have made the build a first-class target. In that landscape a flaw that turns a Git source into command execution on the runner is no longer a lab curiosity — it is the middle step of a compromise chain aimed at secrets, then production. The minimum viable posture is to treat the build daemon as production infrastructure and patch it on the same cadence, rather than as a disposable step.
What to check, concretely
The first step is to learn the versions the pipeline actually uses, not just the one on the developer’s machine:
docker version --format '{{.Server.Version}}'
docker buildx version A CI/CD runner on an old base image can pull a Buildx version far older than the fix. Upgrading goes through the runner image, not the application repository.
Self-hosted runners deserve a special look. A runner often ships its own Buildx and may talk to a remote buildkitd — in Kubernetes, container builds commonly run through a shared BuildKit deployment rather than the host Engine. In those setups the Engine version on the runner says nothing about the BuildKit actually doing the work; read the version from the buildkitd image or from the docker buildx version output of the pipeline itself.
Then treat build sources as untrusted. Do not build from unaudited Git sources with the bundle optimisation enabled, isolate public-fork builds in dedicated runners, and apply Engine and BuildKit updates in the same window as production patches. A build compromised today is a signed image deploying tomorrow.
Verdict
If your builds start from audited internal sources and your base images are pinned, upgrading to Engine 29.7.2 plus an up-to-date Buildx/BuildKit closes the surface — do it in your normal patch window.
If your pipeline builds from public forks, third-party dependencies or untrusted Git sources, treat these six flaws as a redesign trigger: isolate runners, disable the bundle checkout until the fix is everywhere, and update Engine, Buildx and any standalone buildkitd daemon. The command that builds your image is now a code-execution vector like any other.