Friday, August 28, 2009

Securing the web with continuations!

The payoff from the previous posts:

Say Alice is an iframe inside Bob and wants to start a shared library with Bob.

alice.html:


library = {y: {x: "call me Ishmael"}};


bob.html:

var library = makePostMembrane(document.getElementById('alice').contentWindow).getRoot("library");
alert(library.y().x())


Technical aside: unfortunately, Strands etc. do not support continuations captured in redefined field accessors (setters/getters), so I didn't quite achieve the transparency goal of "library.y.x", but close :) Maybe try hacking in support if I have time.

The architecture is somewhat interesting:
  1. One cross-frame 'networking' library for using the string-passing abilities of postMessage to make sharing closures and objects between frames no different from passing to them to functions/actors in the same context: no more JSON and strange asynchronous protocols.
  2. Optionally, our membrane library
  3. More optionally, one of our view/policy libraries

Digging deeper..

To build 1), transparent sharing, we load libraries to CPS the page and construct proxy objects that proxy shared-object interactions between frames viz. the asynchronous postMessage primitive for passing strings between frames. Pretty quickly, it's clear there are distributed object usage concerns like deadlock. Our library helps a bit (e.g., handshaking for initialization and caching), but the push for process-per-origin/process-per-frame has created serious usability problems. The pickling support doesn't help you with the concurrency, and my tactic of using continuations hides the ugliness in the typical case, but, in reality (and, arguably, in the normal code without the library), there are yields in the middle of event handling! Invariants might not be held when control is resumed if folks aren't careful. Perhaps flapjax to the rescue? :) A transactional approach might make sense... but then again... I suspect it'd be horrendous in this domain: transparency is the goal.

Now 2) If, instead of exporting say "window" to be shared, we exported a fresh "membrane(window)" for every iframe, we can, at any time, turn on/off or even modify access to shared objects and even be selective about for which principal. Again, for free. Sort of like flying with Python, but safer. Complete mediation ftw! Also happens to be the first true aspect system for JavaScript and introduces a new notion of secure advice.

Writing behavior for 2) from scratch and per-field/object/method/etc. is cool at first, but quickly, you hit repetitive abstractions. Enter 3): a binary yes/no policy language (the 'who' is whoever has the object reference; the action is 'invoke', so all that is left is the yes/no choice on the resource). That's not quite true: introducing exceptions on DOM access might break programs, so we might want to semantically hide elements. Generalizing, we see we just want to create a secure bidirectional view , which we do for a useful case. Would be fun to create more combinators :)


... and now... benchmarking and updating the writeup :(

No comments: