Portainer accepts JWT bearer tokens via ?token= URL query parameter on any authenticated API endpoint, in addition to the standard Authorization: Bearer header. The extractBearerToken function in api/http/security/bouncer.go reads the token from query.Get(“token”) before falling back to the header. Although query.Del(“token”) scrubs the parameter from r.URL.RawQuery inside Portainer, the original full URL including ?token= has already been logged by any upstream reverse proxy, load balancer, or access logger. Browser history also records the URL, and the HTTP Referer header leaks the token when the user navigates from the Portainer UI to an external site. The ?token= parameter was used by Portainer’s browser-based container attach, exec, and pod shell features for WebSocket upgrades. Any user with exec or attach rights on a container can expose their token, not just administrators. A leaked token grants the full privileges of the issuing user for its validity period (default 8 hours, configurable). Attack complexity is high because exploitation depends on obtaining a leaked token from logs, referer, or shared URLs. But once obtained, an administrator token compromises confidentiality, integrity, and availability of Portainer and all managed Docker/Kubernetes environments. Container exec can reach the host filesystem, enabling host-level compromise. Affected versions include all Portainer releases before 2.33.8 (LTS), 2.39.2 (LTS), and 2.41.0 (STS). The fix removes query-parameter token acceptance entirely, switching to Authorization header for API clients and an HttpOnly cookie for browser UI WebSocket upgrades.
dailycve form:
Platform: Portainer
Version: Up to 2.40.x
Vulnerability: JWT via query
Severity: High
date: 2026-03-06
Prediction: Expected patch 2026-05-07
What Undercode Say:
Search reverse-proxy access logs for leaked tokens
grep -E '\?token=|&token=' /var/log/nginx/access.log
Simulate token extraction from referer
grep 'Referer:.?token=' /var/log/apache2/other_vhosts_access.log
Nginx rewrite to strip ?token= before reaching Portainer
location / {
if ($args ~ (.)(^|&)token=[^&](.)) {
set $args $1$3;
}
proxy_pass http://portainer:9000;
}
Curl test with stolen token
curl -H "Authorization: Bearer <STOLEN_JWT>" https://portainer.example/api/endpoints
Exploit:
Attacker gains access to any log (reverse proxy, WAF, browser history) containing a URL with ?token=. From an external site, if a Portainer user clicks a link, the Referer header leaks the full token. Attacker extracts JWT and uses it in Authorization: Bearer header or directly reuses ?token= against any API endpoint. With admin token, attacker lists containers, executes commands via /api/endpoints/{id}/docker/containers/{id}/exec, and deploys malicious stacks to compromise host.
Protection from this CVE
Upgrade to Portainer 2.33.8 (LTS), 2.39.2 (LTS), or 2.41.0 (STS). If unable, strip ?token= at reverse proxy (nginx/Traefik) before requests reach Portainer. Audit all existing logs for ?token= and treat found JWTs as compromised; reset affected user passwords. Reduce JWT session timeout in Portainer settings. Do not share Portainer URLs containing ?token= and avoid navigating to external sites from unpatched Portainer UI.
Impact
Token leakage to infrastructure logs, browser history, and referer headers leads to full account takeover. Administrator token compromise grants attacker complete API control over Portainer and every managed Docker/Kubernetes host, enabling container exec, host filesystem access, and cluster compromise. Default 8-hour validity window allows persistent unauthorized access without password.
🎯Let’s Practice Exploiting & Learn Patching For Free:
Sources:
Reported By: github.com
Extra Source Hub:
Undercode
To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent may adversely affect certain features and functions.
We do not sell your personal data. If you wish to exercise your rights under applicable privacy laws, please visit our Do Not Sell My Personal Information page.
Functional
Always active
The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
Preferences
The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
Statistics
The technical storage or access that is used exclusively for statistical purposes.The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
Marketing
The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.