7 ms·
This is one of the cleverest things I've seen in JS in a while. In a nutshell, they use a same origin iframe to ensure the plugin gets its own copy of globals
by osrec 7y ago
This is one of the cleverest things I've seen in JS in a while.
In a nutshell, they use a same origin iframe to ensure the plugin gets its own copy of globals (so it can't mess up the globals your app uses), coupled with a proxy object which whitelists certain globals for the plugin to use along with certain vars from your app.
Really rather clever, although the guys who develop browsers should consider an API for something like this as it's becoming such a common use case.
- robinricard 7y agoThe Realms polyfill is a polyfill for an actual TC39 JS proposal [0]. It's currently at stage 2. If the proposal gets accepted, you will not need the polyfill. This would also work with any JS embedding (browsers, node, etc...) as it would be baked in the language. [0]: https://github.com/tc39/proposal-realms https://github.com/tc39/proposal-realms
- lern_too_spel 7y agoIt is possible to skip the iframe if you use a compiler. This was used by OpenSocial implementations more than a decade ago. https://en.m.wikipedia.org/wiki/Caja_project https://en.m.wikipedia.org/wiki/Caja_project
- osrec 7y agoInteresting, but who is responsible for the compilation? The plugin developer? The app developer? The realms approach feels a bit cleaner to me... I would think it's also easier to debug than trying to debug compiled code.
- lern_too_spel 7y agoThe host page must control the compilation to ensure the safety of its data. The compiled code is still JavaScript, just without any access to variables that the host does not want the embedded script to see.
- osrec 7y agoWell, it's an option, but I would probably just go with the iframe approach as it seems like less hassle + cleaner!
- lern_too_spel 7y agoIt has less bloat if you use lots of embedded scripts. My point is that this problem has been solved before in an even cleverer way and was used by hundreds of engineers in MySpace's heyday, so I'm surprised the authors had not considered it.
- rudi-c 7y agoWe did! But while the approach was perfectly plausible in theory, we didn’t feel good about it. We didn’t find anybody currently using this approach in production. Projects like Caja seemed unmaintained. So we’d have to reason about the security properties ourselves, but it’s hard because those approaches are more blacklist centric (remove unsafe JS features) than whitelist centric. They also did more than we needed, which increases the attack surface area. There’s some papers on the topic that formalize Javascript in order to write proofs about it, but they’re quite old and some newer Javascript features like async/await definitely could invalidate some of assumptions behind these proofs. While I don’t know the exact history, the Realms work does derive from Caja, it’s just the latest in this line of evolution.
- mixonic 7y agoIndeed, those who develop browsers are on it! https://github.com/tc39/proposal-realms https://github.com/tc39/proposal-realms
- mikepurvis 7y agoGoogle Gadgets (on the iGoogle custom homepage) used a similar scheme for exposing a select API to untrusted JS running in frames. I was mostly exposed to it because Mapplets used the same backend to allow user widgets on Google Maps. The proxy Maps API objects (used to spawn map markers and so on) were similar in API to their non-proxy counterparts, though obviously every interaction with the other-frame content became asynchronous, and that led to a bunch of interesting small differences that could trip you up if you didn't appreciate the reality of all your data being copied back and forth across that boundary.
- m-p-3 7y agoWhy did you remind me of iGoogle, I miss it so much :(
- wp381640 7y agothat was an entire startup category a decade ago that raised a bunch of VC - netvibes and pageflakes come to mind
- martin-adams 7y agoMy browser homepage is still igoogle.com as I’ve been too lazy to change it
- aidos 7y agoThe with(proxy) pattern is super clever. It looks like that was created by someone else. Kudos to whoever came up with it. It’s a really nice hack.
- erights 7y agoThanks. The "with(proxy)" part specifically would be mine. The old Google Caja, from the EcmaScript-5 days preceding Proxies, did something similar: https://github.com/google/caja/blob/master/src/com/google/caja/ses/startSES.js#L771 https://github.com/google/caja/blob/master/src/com/google/ca... The full new pattern, combining "with(proxy)" with a clever use of direct "eval", is from Caridy Patino of Salesforce. The modern Realms Shim https://github.com/Agoric/realms-shim https://github.com/Agoric/realms-shim , and the SES Shim which builds on it https://github.com/Agoric/SES https://github.com/Agoric/SES , is a collaboration of Agoric and Salesforce, especially JF Paradis of Salesforce. We have come to refer to the fragment of code with the "with(proxy)" and the direct "eval" as the "Eight magic lines of code" and "The heart of the shim". It is explained at https://www.youtube.com/watch?v=9Snbss_tawI&list=PLKr-mvz8uvUgybLg53lgXSeLOp4BiwvB2 https://www.youtube.com/watch?v=9Snbss_tawI&list=PLKr-mvz8uv... and https://www.youtube.com/watch?v=mSNxsn0pK74&list=PLKr-mvz8uvUg70w0yKGfytaDqxiIBNo_L https://www.youtube.com/watch?v=mSNxsn0pK74&list=PLKr-mvz8uv...