In the spirit of WASM being a strong sandbox, hosts need tools to mitigate intentional and accidental denial-of-service attacks from untrusted guests. In a JavaScript host, using the WebAssembly
global, it seems like it is very hard to accomplish this in an ergonomic way.
By its nature, JavaScript is single-threaded and blocks on calls to exported guest functions. As a result, it has no mechanism to cancel that operation unless the canceller is in another isolate. There is no built-in way to invoke an exported function with a predetermined deadline. So a JavaScript host needs to spin up workers (according to runtime) to execute the guest functions. It can then enforce deadlines and cancellations from the event loop that has references to the workers.
This seems like a pretty critical flaw in the WebAssembly
interface itself. Is there somewhere with deeper discussion on this? Is it 'on the radar' of the right people?
I haven't really seen any discussion about this sort of thing in the JS WebAssembly
API. I'd file an issue on the webassembly/design
repo if you wanted to kick off that discussion.
FWIW, JS is generally considered by browsers to be in the same sandbox as wasm. That is, it's all untrusted guest code to the browser, and they don't really differentiate between JS vs Wasm (modulo the semantics around wasm imports and not gaining ambient authority to call any JS function).
Also, another option is to pre-process the wasm to insert fuel or something like that if you have this particular use case of wanting to avoid DoS in your JS app due to infinite loops or whatever in your Wasm
Web workers are the canonical solution to blocking computation in browsers
Maybe you could clarify what the problem is with that solution?
I would say that the problem with the status quo is one of ergonomics; the approach to spawning Workers on different JavaScript runtimes is often quite different. It requires the introduction of quite a bit of complexity that is unrelated to WASM to safely consume the tech.
The tools for publishing re-usable code that can be consumed on each of these runtimes is also very difficult. JavaScript is already horrible when it comes to packaging and publishing anything requiring a separate entrypoints being available across runtimes.
JS is generally considered by browsers to be in the same sandbox as wasm. That is, it's all untrusted guest code to the browser, and they don't really differentiate between JS vs Wasm
That sounds like a very plausible explanation. I bet the server-side runtime and untrusted guest use-cases weren't key factors in the design of the WebAssembly
API.
I've found this issue on GitHub that appears to have some background discussion: https://github.com/WebAssembly/design/issues/1345
Last updated: Dec 23 2024 at 12:05 UTC