HACKER Q&A
📣 tjchear

How to safely execute user code in browser (like observablehq)?


The environment within which the code could execute could belong to other users, how can we do this safely? My initial high level thought is 1) custom domain, 2) iframe security policies, 3) setting some https headers? 4) execute in web worker 5) message passing back to host to modify UI, but I don't know the details, and I may have missed other things.


  👤 tmcw Accepted Answer ✓
Yep: custom domain, iframe security policies. Communicate with the iframe via postMessage only, be strict about message origins, and have limited trust in those messages, too. Strict CSP policies and use the 'sandbox' iframe attribute.

iframes are cruddy, but they are designed for this - the long era of iframe-based embedded advertisements caused vendors to double-down on those security policies.

Observable doesn't use WebWorkers, duktape, or a custom JavaScript interpreter. If you had sandboxed JavaScript that didn't need access to the DOM, those might be options, but if you want people to write JavaScript like usually, they don't do any good.


👤 davisr
You don't, and it would be irresponsible. Run it on your server and deliver known-safe results back to the client. Besides, client PCs aren't there to do your bidding--don't offload your responsibilities onto them. You're just asking for a (very inefficient) bitcoin farm.

👤 speedgoose
You need a sandbox but I don't think web-browser sandboxes are designed for your use case, when the web application doesn't trust its own code.

Considering the constraints I would experiment with a virtual machine. It can use your own set of instructions, like high level domain specific instructions in a json, or something lower level like a simple assembly.

You could use qemu in WebAssembly in a webworker and hope for no vm escape hack. Or a lua interpreter implemented in javascript.


👤 QueensGambit
This might be an unpopular opinion, but browser extensions already allow user code to be executed in browser. Your thoughts seem to be along the same lines. You should look at how chrome extensions are executed and follow the same.