A Security Layer That Fails Open
Authorization plugins are how teams put a policy gate in front of the Docker Engine API — "no privileged containers", "no host mounts", "only these images". CI/CD fleets, build farms, docker-in-docker runners and management planes lean on them. CVE-2026-34040 makes that gate approve requests it never actually read.
A single Docker API request with a body larger than 1 MB is silently truncated before it reaches the AuthZ plugin — but the daemon processes the full, untruncated request. The plugin says "yes" to a harmless-looking call; the daemon runs a privileged one. CVSS 8.8, no race, no timing, works over TCP/TLS.
Vulnerability Identity Card
| CVE | CVE-2026-34040 (incomplete-fix regression of CVE-2024-41110) |
| Component | Docker Engine (dockerd) authorization-plugin (AuthZ) middleware |
| Class | Authorization bypass via request-body truncation (CWE-863 / CWE-444-adjacent) |
| CVSS | 8.8 — High/Critical; single request, no interaction |
| Impact | Bypass every AuthZ plugin → create a privileged container → host root |
| Fixed in | Docker Engine 29.3.1 · Docker Desktop 4.66.1 (fail-closed) |
| MITRE ATT&CK | T1211 Defense-Evasion · T1610 Deploy Container · T1611 Escape to Host |
| Relevance | CI/CD, build nodes, DinD runners, any daemon fronted by an AuthZ plugin |
How One Big Request Wins
The Docker AuthZ flow is a middleware: an incoming API call is shown to the plugin, which returns allow/deny, and only then does the daemon act. The bug is a parsing disagreement between the two:
- The middleware buffers the request body to forward it to the plugin, but caps that buffer at ~1 MB and forwards the truncated version.
- The plugin makes its decision on the truncated body — which no longer contains the dangerous fields (or parses as a different, benign request).
- The daemon then reads and executes the complete request, including the parts the plugin never saw.
Pad the request past 1 MB so the security-relevant JSON lands after the cut, and the plugin's verdict is made on a fiction.
# A create request whose "benign head" fits under 1MB and whose # privileged tail (Privileged:true, host bind mounts) sits past the cut. # Plugin approves the head; daemon executes the whole thing. curl --unix-socket /var/run/docker.sock \ -H "Content-Type: application/json" \ -d @oversized-create.json \ http://localhost/v1.45/containers/create # AuthZ plugin: "looks fine"
Exploitation Prerequisites
From Bypass to Host
Bypassing the plugin isn't the prize — the privileged container is. Once the daemon creates one with host mounts, the container is the host:
# inside the privileged container the attacker just got approved: chroot /host # host bind-mounted in via the tail of the request # now read everything the daemon's host has: # ~/.aws/credentials, ~/.ssh/id_*, /etc/kubernetes/admin.conf, kubelet certs # and persist: echo '* * * * * root /tmp/impl' >> /host/etc/cron.d/impl
Risk Propagation
The 2024 Regression
This is the same class of bug as CVE-2024-41110 from July 2024 — an AuthZ bypass that was patched, but not completely. The 2024 fix closed some vectors and left the oversized-body path open. The lesson for defenders: "we patched the AuthZ bypass last year" is not the same as "the AuthZ bypass is gone." Treat the plugin as a defense-in-depth layer, never the only control on privileged actions.
Detection
Privileged:true or host-mount container appearing when policy forbids it — the plugin's own logs will not show the dangerous fields. High.# on each build/runner host
docker ps -q | xargs -r docker inspect \
-f '{{.Name}} priv={{.HostConfig.Privileged}} binds={{.HostConfig.Binds}}' \
| grep -E 'priv=true|/:|/etc|/root|/var/run/docker.sock'Remediation
Immediate:
# Docker Engine >= 29.3.1 (or Docker Desktop >= 4.66.1)
docker version --format '{{.Server.Version}}' # must be >= 29.3.1
# the fix makes oversized bodies fail CLOSED instead of truncating past the pluginPermanent — never let the plugin be the only wall:
- Do not expose the Docker socket or TCP API to workloads or the network. A mounted
/var/run/docker.sockis host root regardless of any CVE. - Prefer rootless / daemonless builds (BuildKit rootless, Buildah, Kaniko) on CI so there is no privileged daemon to bypass.
- On Kubernetes, enforce Pod Security Admission restricted and a Kyverno/Gatekeeper rule denying
privileged,hostPath, anddocker.sockmounts — a control the daemon-side bypass cannot touch.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata: {name: no-docker-sock-no-privileged}
spec:
validationFailureAction: Enforce
rules:
- name: block-sock-and-priv
match: {any: [{resources: {kinds: [Pod]}}]}
validate:
message: "docker.sock mounts and privileged containers are forbidden."
pattern:
spec:
=(volumes):
- =(hostPath):
path: "!/var/run/docker.sock"
containers:
- =(securityContext):
=(privileged): "false"A control that fails open is worse than no control, because it buys false confidence. CVE-2026-34040 is a reminder that admission and authorization layers are software with parsers, and parsers disagree. Patch the daemon, yes — but the durable posture is to stop putting a privileged Docker daemon within reach of untrusted input at all, and to keep a second, independent gate (PSA + policy) that a daemon-side bypass can never disable.
— k8sec Security Research
Find every Docker daemon and socket in reach of a workload.
K8SEC surfaces exposed runtimes, docker.sock mounts and privileged pods across the fleet — the paths a daemon-side AuthZ bypass turns into host root.
Explore K8SECSources: Docker security advisory and release notes for Engine 29.3.1 / Desktop 4.66.1; Cyera research disclosure; The Hacker News and eSecurity Planet reporting; CVE-2024-41110 history via CSO Online. The 1 MB truncation mechanism and fixed versions are drawn from those sources; the exploitation walkthrough is a defender-side reconstruction.
