# Cookie Chaos: How to bypass __Host and __Secure cookie prefixes

Unicode whitespace and legacy $Version parsing let attackers set __Host-/__Secure- prefixed cookies from subdomains, enabling cookie tossing, XSS and session fixation.

- Payout: Research
- Severity: medium
- Program: Django
- Credited: PortSwigger Research
- Disclosed: 2025-09-03
- Write-up quality: 8/10
- Original: https://portswigger.net/research/cookie-chaos-how-to-bypass-host-and-secure-cookie-prefixes
- Library page: https://bugbountylibrary.com/r/blog%3Aportswigger-net-research-cookie-chaos-how-to-bypass-host-and-secure-cookie-prefixes
- Tags: domain:web impact:ato impact:integrity kind:research platform:research sev:medium tech:python technique:parser-differential technique:unicode-normalization vuln:business-logic vuln:xss

**Target:** Cookie header parsing in Django/ASP.NET/Tomcat/Jetty
**Root cause:** Browsers treat a U+2000-prefixed cookie name as non-restricted, but servers (Django .strip(), ASP.NET) trim Unicode whitespace and normalize it to __Host-name; legacy $Version=1 parsing splits one cookie string into multiple cookies.
**Steps:**
1. Set cookie from subdomain via `document.cookie=\`${String.fromCodePoint(0x2000)}__Host-name=injected; Domain=.example.com; Path=/;\``
2. Browser accepts as non-prefixed and sends to all subdomains
3. Server trims U+2000 and treats name as __Host-name, last occurrence wins
4. Alternatively send `$Version=1,__Host-name=injected; Path=/somethingreallylong/; Domain=.example.com;` to trigger Tomcat/Jetty legacy parsing
5. Reflect cookie value unescaped to achieve XSS, or abuse for CSRF/session fixation
**How found:** Noticed RFC 6265 defines Cookie header as octets, hypothesized browser/server decoding mismatch; tested Unicode whitespace chars against Django/ASP.NET and legacy $Version parsing against Tomcat/Jetty.
**Exploitation:** Requires XSS or attacker-controlled subdomain to set the crafted cookie; browser forwards both original and forged cookies, backend picks attacker value, reflected into page yields XSS or session fixation.
**Escalation:** Chains cookie-prefix bypass with reflected XSS or CSRF token overwrite to escalate to account takeover.
**Insight:** Test cookie-name normalization by prefixing protected names with Unicode whitespace (U+2000, U+0085, U+00A0) and legacy `$Version=1,` syntax; check whether backend trims/normalizes while browser does not.
