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.
Content-controlled Javascript is not alright. Content-controlled Javascript is, in fact, why browsers have sandboxes in the first place (think about this: if they could get away with less, they would; and in the current security model, you don't get to sandbox yourself from your content when you are the content, so you don't get to get away with anything.) You need some sort of stable base, living in the client, to build any sort of cryptographic security upon. That means, at the very least, Javascript that comes from a file: or blob: URI.
You can use SSL to bootstrap up to that, delivering an initial payload which will then be loaded. But you can't keep the advantages of the web-app model (refreshed from the server with every page-load! embed arbitrary DOM content by URL!) when you do this; you have to switch to thinking like a local-app developer, who downloads and sig-checks "updates", and who downloads and validates "content" (so your image doesn't turn into a script half-way through), before making use of either. Effectively, you don't have a web-app any more.
You can't take any web-app that's already been written and just "throw in" a crypto library, and consider yourself secure. You aren't. Don't listen to the article. Either trust SSL (i.e., trust your crypto provider with your plaintexts), or use some sort of locally-fixed-client implementation: if not a native app, then at least a Chrome App or something.
- Does that mean a site like passpack is only waving its hands at its security, and that its client-side cryptography is irrelevant and basically insecure??