Docker Had a 10-Year Security Bypass Hidden in Plain Sight

Want to learn ethical hacking? I built a complete course. Have a look!
Learn penetration testing, web exploitation, network security, and the hacker mindset:
โ Master ethical hacking hands-on
Hacking is not a hobby but a way of life!
Docker’s Security Layer Has Been Broken Since 2016, And The Fix Doesn’t Finish the Job. One padded HTTP request. That is all it takes to silently disable every authorization plugin in Docker, open a direct path to the host filesystem, and walk out with AWS credentials, SSH keys, and Kubernetes cluster access. The authorization logs show nothing unusual. ๐
When a request hits the Docker API, an authorization plugin steps in before anything else happens. That plugin checks exactly what is being requested before the Docker daemon gets to act on it, and enterprises run tools like Open Policy Agent, Prisma Cloud, or Casbin for this job, configured with rules about what containers are and are not allowed to do.
CVE-2026-34040, with a CVSS score of 8.8, breaks that completely. When an HTTP request body exceeds one megabyte, Docker’s middleware silently drops the body before passing the request to the authorization plugin. The plugin receives nothing, cannot block what it was never shown, and approves the request because it sees nothing suspicious. The Docker daemon then processes the full original body, creates the container exactly as requested with every dangerous option intact, and the security check that was supposed to stop it never ran.
The exploit is simple. An attacker adds a dummy padding field to the JSON body of a container creation request until the total size crosses one megabyte. Docker’s JSON parser ignores the extra field entirely, the authorization plugin sees an empty body and approves, and the daemon reads the real request and launches a privileged container with the entire host filesystem mounted at /host. One padded HTTP request. That is the whole attack.
100 bytes: denied. 2 megabytes: welcome aboard.
Once that container exists, AWS credentials, SSH keys, and the kubeconfig that controls Kubernetes clusters are all sitting there. On a cloud instance with an IAM role attached, the EC2 Instance Metadata Service at 169.254.169.254 is reachable from inside that container too. One request and an attacker is reading the same credential files the development team opens every morning, with access to everything those credentials unlock.
Privileged containers are just the start. The bypass blinds the plugin to everything it checks: host network access, dangerous kernel capabilities like SYS_ADMIN, seccomp profiles, AppArmor, device access, image allowlists, and command restrictions. Every policy that depends on inspecting the request body fails equally, and it does not matter how sophisticated those rules are if the body never arrives.
This bug has been in the Docker codebase since Engine version 1.10, released in February 2016. Ten years. A constant called maxBodySize, sitting at line 19 of authz.go, has been responsible for silently dropping oversized request bodies the whole time. In 2024, CVE-2024-41110 exposed the zero-length version of the same attack, where sending an empty body caused the plugin to approve a request it should have blocked. Docker patched that in July 2024 by adding a check for Content-Length larger than zero and stopped there. Nobody asked what happens at the other end of the boundary. Cyera Research read that patch, saw the condition, and sent a request larger than one megabyte instead of zero. The answer was already sitting in the source code at line 19 of authz.go, right there in plain sight.
Four independent researchers found it simultaneously and reported it separately: Vladimir Tokarev from Cyera Research, Oleh Konko, Cody, and Asim Viladi Oglu Manizada. Docker responded fast. The report went in on March 24, 2026. Docker Engine 29.3.1 shipped the next day. Docker Desktop 4.66.1 followed two days after that. The fix changed the behavior so that oversized requests are now rejected with an error instead of silently stripped and passed through.
The official CVSS score lists Attack Vector as Local, which reflects how the Docker socket works by default as a Unix socket on the local machine. In enterprise environments, CI/CD pipelines, and management platforms, the Docker API runs over TCP with TLS across the network, which makes the practical attack vector broader than the official score reflects.
The 8.8 score deserves a closer look. The predecessor, CVE-2024-41110, scored a perfect 10.0. Same vulnerability class, same impact. The difference is how Docker scored the attack vector: Local instead of Network. Their reasoning is that the Docker socket is a Unix socket by default. Cyera disagrees, pointing out that enterprise deployments run the Docker API over TCP across the network. Two bugs, same class, same impact. One scores 10.0, one scores 8.8.
The 29.3.1 fix handles the request side. The response side was not touched in the same patch. When a response body crosses 64 kilobytes, Docker sends it to the client before the authorization plugin finishes checking it, which means plugin policies designed to catch sensitive data in responses, like container inspection output containing environment variables or execution results, never actually run on large responses. That behavior is still present in the patched version. Mirantis Container Runtime is built from the same upstream Moby codebase and had not published a specific advisory at the time of disclosure, so anyone running MCR needs to confirm with Mirantis whether their version contains the fix.
AI coding agents running inside Docker sandboxes are standard infrastructure in 2026. They need Docker API access to spin up containers, run test environments, and manage services, and the authorization plugin is supposed to be the safety net that keeps them from doing anything dangerous. When one of these agents hits a denied request, it does not open a ticket and wait. It reads the error, researches the mechanism, finds the source code, and starts working around the problem, because that is what it was built to do. Cyera described exactly this: an agent debugging a Kubernetes memory issue gets blocked trying to mount a kubeconfig from the host, finds CVE-2024-41110 while researching, reads the patch, notices the size boundary the fix does not cover, and sends a padded request on its own. No attacker involved. No malicious intent. Just a tool solving the problem it was given very thoroughly.
Claude Code did exactly this kind of thing in March 2026, bypassing two of its own security layers while completing a legitimate task with zero adversarial prompting. CVE-2026-34040 does not need anything close to that level of complexity. It is a JSON field with padding.
The attack chain looks like this. An attacker pushes a project to GitHub with hidden instructions in a dotfile or code comment. A developer asks an AI coding agent to set up the development environment. The agent clones the repository, reads the project files, follows the embedded instructions, and executes attacker-controlled code inside the sandbox. That code pads a container creation request past one megabyte, the authorization plugin sees an empty body and approves, a privileged container launches with the host filesystem mounted, and AWS credentials, SSH keys, and Kubernetes access tokens are read out and sent to a remote server. The same attack SCARLETEEL demonstrated in 2023, where attackers jumped from a compromised Kubernetes pod to stealing over a terabyte of AWS data, but this time starting from a legitimate AI agent setup that followed Docker’s own security recommendations.
This is not a theoretical scenario. On March 31, 2026, attackers compromised the npm account of an Axios maintainer and published two malicious versions of the package. Axios has over 100 million weekly downloads. The malicious versions slipped in a hidden dependency that ran a RAT through a postinstall hook, targeting macOS, Windows, and Linux, and those versions were live for just three hours before being pulled from the registry. Three hours is how long it takes to reach millions of environments when a package is trusted everywhere. Any AI agent that ran npm install during that window executed the payload automatically, without any human clicking anything. The delivery mechanism for step one of this attack chain already happened in the real world, three weeks before this CVE was published.
The authorization plugin logs look completely clean throughout all of this. Every request shows as allowed with an empty body. The only trace is a single warning line in the Docker daemon logs that reads "Request body is larger than." After patching, even that disappears, so search the daemon logs before upgrading if there is any concern about whether this was already exploited.
Here is how to check exposure and what to do about it.
- โ Run
docker version --format '{{.Server.Version}}'to confirm the Engine version. Anything below 29.3.1 is running vulnerable code. - โ Run
docker info --format '{{.Plugins.Authorization}}'to check whether authorization plugins are configured. If plugin names are returned, the deployment uses AuthZ and is directly at risk. - โ Search daemon logs for evidence of exploitation using
journalctl -u docker | grep "Request body is larger than". This log message fires at exactly the moment the middleware drops a body before the plugin sees it. Correlate any hits with container creation events at the same timestamp. - โ Check for unexpected privileged containers with
docker inspect --format '{{.Name}} Privileged={{.HostConfig.Privileged}}' $(docker ps -aq) - โ Check for suspicious host mounts with
docker inspect --format '{{.Name}} Binds={{.HostConfig.Binds}}' $(docker ps -aq). - โ If anything looks off, check access timestamps on credential files with
stat ~/.aws/credentials ~/.ssh/id_rsa ~/.kube/configbefore doing anything else. If those files were accessed during the suspicious window, treat it as a confirmed breach and check CloudTrail for unexpected API calls, SSH auth logs on production servers, and Kubernetes audit logs for cluster access. - โ Patch immediately by upgrading to Docker Engine 29.3.1 or Docker Desktop 4.66.1.
- โ If patching is not immediately possible, add a 512 kilobyte body size limit at the API gateway to block bypass attempts while the upgrade is prepared.
- โ Lock down Docker API access. If an AI coding agent or CI/CD system does not need to create containers, that API endpoint should not be exposed to it.
- โ Run Shodan query
port:2375 product:Dockerto check whether the Docker API is reachable from the internet. An exposed unauthenticated Docker API is already a serious problem, and CVE-2026-34040 makes it significantly worse. - โ If running Docker in rootless mode is an option, do it. In rootless mode, even a privileged container’s root maps to an unprivileged host UID, which means a successful bypass no longer results in full host compromise. It does not fix the vulnerability, but it limits the damage significantly if exploitation happens before patching.
Understanding how attackers get from an initial foothold to complete control of a system, including privilege escalation and post-exploitation techniques, is exactly what I cover in my ethical hacking course.
If you want to understand why I never use Docker and how container escapes actually work in practice, I made a full video breaking this down. Different CVEs, same fundamental problem. Containers were never a security boundary, and this video shows exactly why.
Hacking is not a hobby but a way of life.
Sources: Cyera Research โ One Megabyte to Root ยท Docker GitHub Advisory โ GHSA-x744-4wpc-v9h2 ยท NVD โ CVE-2026-34040
โ Stay updated!
Get the latest posts in your inbox every week. Ethical hacking, security news, tutorials, and everything that catches my attention. If that sounds useful, drop your email below.