demo · v139
XSS Sidechannel
The reason for the removal: an attacker who could plant raw bytes on a page that didn't declare its charset could trigger ISO-2022-JP auto-detection and smuggle script in via escape sequences. Below: the same byte stream interpreted as UTF-8 (safe) and as ISO-2022-JP (script executes pre-v139). Toggle the declared charset and see which engine path runs.
victim page (rendered)
what just happened
—
raw HTML the attacker would inject (visible as text below)
<p>harmless text</p>
<!-- the next bytes look meaningless in UTF-8 but trigger ISO-2022-JP mode -->
\x1b$B (escape sequence) ... <script>alert("xss")</script> ... \x1b(B
why removal closes the door
Chrome's content-sniffing code looked at the first bytes of an undeclared HTML response. If it saw an ISO-2022-JP escape sequence (0x1B 0x24 0x42), it reinterpreted the entire stream in that encoding. Attackers used the difference between server-side string sanitisation (operating on UTF-8) and client-side rendering (in 2022-JP mode) to smuggle <script> tags through XSS filters. Use counter showed only ~0.000002% of pageloads used it; Safari already disabled it. Removing the sniff closes the sidechannel.
how to be safe (forever)
// Always declare your charset explicitly. Both work in any browser.
<!doctype html>
<meta charset="utf-8">
// Or set it server-side:
Content-Type: text/html; charset=utf-8