PortSwigger Reveals Cookie Prefix Bypass Techniques Affecting Major Frameworks
PortSwigger Research discloses methods to bypass __Host and __Secure cookie prefix protections using Unicode whitespace and legacy parsing, affecting Django, ASP.NET, and Java-based servers.

PortSwigger Research has published a detailed analysis of techniques that allow attackers to bypass __Host and __Secure cookie prefix protections in major web browsers. The research, presented at SteelCon, identifies critical discrepancies between how browsers and servers validate these prefixes, enabling the overwriting of security-critical cookies. The findings affect session integrity across Chrome, Safari, and other browsers, and highlight gaps in cookie prefix enforcement that can lead to session fixation, cross-site scripting, and privilege escalation.
The core issue lies in how browsers and servers handle cookie encoding. According to RFC 6265, the Cookie header is a sequence of octets, not characters, meaning the browser sends raw bytes and the server decodes them. If the browser and server interpret those bytes differently, parsing discrepancies occur. PortSwigger researcher demonstrated that by using Unicode whitespace characters like U+2000 (en quad), an attacker can disguise a restricted cookie such as __Host- in a way that bypasses browser protections. The browser treats it as a non-restricted cookie, but the server may normalize it, interpreting it as a protected one.
A minimal proof of concept uses `document.cookie=${String.fromCodePoint(0x2000)}__Host-name=injected; Domain=.example.com; Path=/;`. The whitespace-prefixed cookie is accepted by the browser as a non-prefixed value and sent to all subdomains. Server-side frameworks like Django and ASP.NET apply trimming to cookie names before processing. Django uses Python's `.strip()` method, which removes a wide range of Unicode whitespace characters including U+2000, effectively converting the cookie name to `__Host-name`. This allows an attacker to inject a forged __Host- cookie from an untrusted subdomain.
Safari handles this case differently—it does not support multibyte Unicode whitespace in cookie names, but single-byte characters like U+0085 (NEL) and U+00A0 (non-breaking space) are still permitted. Additionally, legacy cookie parsing behavior can be abused. If a Cookie header begins with `$Version=1`, some Java-based web servers like Apache Tomcat and Jetty switch into legacy parsing mode, interpreting a single cookie string as multiple separate cookies. This allows an attacker to bypass prefix checks and inject high-privilege cookies from a subdomain or over an insecure origin.
In a full attack scenario, an attacker with an XSS vulnerability can inject a forged __Host- cookie using JavaScript. The browser sends both the original and attacker-controlled cookies. Many frameworks, including Django, resolve conflicts by accepting the last occurrence, giving precedence to the attacker's value. If the application reflects this cookie value without proper encoding, it results in XSS. Alternatively, if the cookie is used for CSRF protection or session identification, this can lead to session fixation or privilege escalation.
Django responded to the vulnerability report by stating that the official documentation warns against permitting cookies from untrusted subdomains, and thus it was not treated as a security vulnerability. PortSwigger emphasizes that the same cookie can be interpreted differently by browser and backend, quietly breaking cookie confidentiality and integrity. To help test for these issues, the researcher created a lightweight Custom Action for Burp Suite that detects conditions where a backend may be vulnerable to cookie prefix bypasses.
This research concludes a series on cookie parsing inconsistencies. It underscores the need for developers to be aware of these discrepancies and to implement proper input validation and encoding. The findings also highlight the importance of consistent cookie handling across browsers and servers to maintain security guarantees.