Also true, for the time being, in most browsers. (Sort of like how "SSL is broken because we don't have certificate pinning yet" is true, for the time being, in most browsers.)

To make sure I understand, let me expand: you're talking about web apps that ever load external assets besides their code package, and then embed those external assets directly into the DOM by giving the DOM the URL (this covers anything from an <img src=""> to a <link rel="Stylesheet" href=""> to a <script src=""></script>).

This doesn't cover, on the other hand, resources that are retrieved by the code-package into HTML5 ArrayBuffers/Blobs/Files, then validated against a cryptographic signature transmitted over the trusted crypto (SSL or code-package-custom) before the resources are allowed into the DOM through data:/blob: URIs.

These resources, of course, must be self-contained--they can't refer to other resources by URL (which would then be loaded directly by the DOM), only to other data:/blob: URIs. You basically need to pre-parse and "static-check" any HTML, CSS, or Javascript you plan to embed--transitively, spidering referenced URLs--before embedding. This runs into the Halting problem in extremis; if a script you want to embed dynamically builds URLs, you're kind of screwed.

But all this is a diversion from the real problem here, which is that web-applications are inherently not sandboxed from their own "trusted" third party code. You're pretty much "letting Jesus take the wheel" (Jesus being the SSL certificate authorities) when you stick a URL into your web-app's DOM.

The solution, obviously, is to let web-apps have another layer of sandboxing between them and their "content." And there are browsers that do this for web-apps, in specific circumstances; you just usually don't call the result a "web-app." Firefox and Chrome will treat their extensions (which are, in fact, HTML+JS+CSS) this way; Chrome will also treat its "apps" this way (which includes "apps" loaded by URL, instead of being delivered in the .crx!); as will my favorite RIA-toolkit-du-jour, node-webkit. We just need this "fully sandboxed DOM cut-point" feature for the web as a whole.

As far as I know, the only reason we don't have DOM-subtree sandboxing is the potential for iframe-based clickjacking. If we can figure out a way to avoid that specific problem, we'd likely get this feature quite immediately--the code for it is, in most cases, already there. I think we will, eventually. Until then, the data:/blob: workaround is pretty good in limited cases; you rarely need to load HTML/CSS/JS "content" (the kinds that can have transitively-embedded DOM URL references), but can instead build those locally from AJAX conversations, and just verify that the content you do want to embed (images, say) is in a benign file-format before translating it into a blob:.

---

My own favorite solution, by the by, would be something like the Chrome Web Store, but a lot more transparent: you browse to https://example.com/, and if that's registered as a domain "owned" by a web-app in this browser-service, it downloads and zero-config installs the app code-package, temporarily (not yet granting it any permissions in the process) and presents it as if that is exactly what is "at" that URL. This could be combined with storage of an initial pre-HSTS cert, if you do want to use SSL. This means you're implicitly switching from trusting CAs to trusting the browser-manufacturer... but you're doing that anyway by installing the browser in the first place.