I'm glad this article includes the only credible fix for the HTTP leak problems: CSP.
A useful thing I learned recently is that, while CSP headers are usually set using HTTP headers, you can also reliably set them directly in HTML - for example for HTML generated directly on a page where HTTP headers don't come into play:
<iframe sandbox="allow-scripts" srcdoc="
<meta http-equiv='Content-Security-Policy'
content='default-src none; script-src unsafe-inline; style-src unsafe-inline;'>
<!-- untrusted content here -->
"></iframe>
It feels like this shouldn't work, because JavaScript in the untrusted content could use the DOM to delete or alter that meta tag... but it turns out all modern browsers specifically lock that down, treating those CSP rules as permanent as soon as that meta tag has loaded before any malicious code has the chance to subvert them.I had Claude Code run some experiments to help demonstrate this a few weeks ago: https://github.com/simonw/research/tree/main/test-csp-iframe...
And any additional CSP directives can only narrow what's allowed. Also works with headers plus <meta> - <meta>s can restrict the CSP even more than what the headers specified, but they can't widen it.
Wow - I had no idea. That's really useful, and probably much easier to implement by javascripters than something that might be set in nginx.
I read this whole post silently mouthing a "CSP" mantra as each new vulnerability was discovered, years apart no less. Elated when I got to the revelation towards the end.
But for all my self righteous bluster the inline version was news to me. Hacker news. Awesome. Thank you.
An idea I’ve been kicking around (which isn’t quite applicable to this use case, I think) is to aggressively restrict the Sec-Fetch- headers on user content. If a server is willing to serve up an untrustworthy SVG, it could refuse to serve it at all unless Sec-Fetch-Dest has the correct value, and ‘document’ and ‘iframe’ would not be correct values. This would make it more difficult to fool a user or their browser by, for example, linking to an SVG file, or using a less-secure mechanism like embed to load it.
This should be in addition to heavily restricting CSP on user content. (Hmm, surely all images should be served with the CSP header set.)
Nice, favorited... thinking this could be useful for an email reader to support css, but not scripts.
I did not know about `srcdoc`, but it looks like that's still vulnerable to injection by using a double quote and </iframe> to escape the sandbox. If this is constructed in a hygienic way using DOM manipulation, it seems like it could work, but it definitely seems possible to screw up.
[dead]
iframe sandboxing is wildly underleveraged. I think it's because it doesn't work well with "modern" app development - you need the ability to slice bits and pieces out yourself.
I've been just using plain typescript/html and it's so easy to say "yeah all of that rendered content goes into an iframe", I've got all of d3 entirely sandboxed away with a strict CSP and no origin.
I do hope that iframe sandboxing grows some new primitives. It's still quite hacky - null origins suck and I want a virtual/sandbox origin primitive as well as better messaging primitives.