Segregate Third-Party JS Libraries
Typically, web authors simply load whatever library they’d like to use with full trust. In JS, such loading amounts essentially to a #include
. I’m flabbergasted that this practice remains normal. It could be paranoia, but even without invoking all the security concerns, I’d be reluctant to include other people’s code simply because of the potential for a naming conflict on a global variable.
But, recently, in reviewing a new paper about JS information flow security, I had an interesting thought. (I should credit this thought to my co-worker, Christoph Kerschbaumer, because it was his phrasing of a bullet point that made me question existing practice.) Why don’t we use iframes to segregate the included code?
Currently, that can’t be done because the inter-iframe communication channel is hideous: uses fragment identifiers in a url to re-navigation a frame, which continuously polls the document url looking for that update. Of course re-navigation has it’s own security issues[Securing Frame Communication in Browsers]. This mechanism just operates too slowly and unreliably to use with a library.
Additionally, there’s a strong reason to keep iframes completely separate from each other: advertisements. Where a JS library is third-party code that you want to use, advertisement code is something that you expressly don’t want polluting namespace or accessing your variables and memory. Because of syndication, it’s also code that you shouldn’t trust in any way. iframes currently provide the best mechanism to segregate an advertisement from the rest of the page.
But! what if the iframes came equipped with a communication channel specifically meant for inter-frame communication? This channel, should of course come with a mechanism to attach security monitors so that each use can be customized for an appropriate level of security. The presence of the channel should act also as a telephone: that is, JS on either side, should be able to opt-out, and not answer a request for communication from the transmitter. The channel will need to be high-bandwidth, so that it can be used with libraries. And the segregation can use either message-passing semantics [good for memory separation (parallelism), might cost copies during communication (c.f. erlang for how to optimize this)] or reference-passing semantics [less communication overhead, bad for memory separation, potential for abuses: library might access complete data structure via referential transitivity].
I think the advantages here are pretty cool:
- If the browser can execute iframes in separate memory spaces, perhaps this could be a way to have parallel code execution.
- The iframe keeps untrusted JS behind a monitored firewall.
- The ability to attach a security monitor to the channel should mollify most complaints about cross-iframe script contamination.
- Talking to an iframe can have its own linguistic support by creating a JS object with overloaded getter/setter that wraps the communication. Calling library methods should look nearly the same as before, modulo a prefix for the interface (which is good, more like including a module).
Update Tue Mar 13 20:45:34 PDT 2012: Christoph alerted me that I have to be more careful in my reading. Indeed, Barth’s paper (cited above) actually contains exactly this proposal, as well as an implementation (adopted in WebKit), postMessage
. The remaining difficulty lies in library adoption. Many JS libs now have to be rewritten to use the new communication mechanism (or clients have to care enough to write wrappers).