[0] https://bugs.chromium.org/p/chromium/issues/detail?id=835887
How do you even go about getting rid of WRX in a JIT? Do you generate and then remove W?
Remove Array buffers, remove blob support, remove anything which can be used to assembly a continuous binary without passing some sanitation.
exploit("X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*")
Okay, so we remove strings. Good thing the in-memory object format isn't known by the atta– wait. Okay, never mind; we can get rid of objects too. And bignums, while we're at it; that leaves us just with bog-standard floating-point integer primitives. Which are stored in a JavaScript call frame. Oops.2. Can be sanitised to be valid UTF-16
3. Can be intentionally mangled in memory to prevent abuse
2. Won't help.
3. Simply reverse, or make use of, the mangling.
I can check browser memory with a profiler and see if this page is marked as executable. It would not be.
JS strings are not UTF-16, they are 16-bit chunks of (potentially) nonsense, and enforcing valid UTF-16 would break quite a few existing uses. For example, anything that stores encrypted data in a string. Which "shouldn't" be done, that should be a Uint8Array, but existing APIs basically force you to do it. And there's such a thing as backwards compatibility.
Your 3rd point is much more feasible. I doubt any "real" mangling would be good enough from a performance standpoint while still being too difficult for attackers to use. But I could imagine eg breaking any invalid UTF-16/UTF-8 string up into separate rope nodes, maybe even ensuring the nodes don't get allocated too close to each other and/or injecting disrupting hardcoded bytes in between them. (I work on SpiderMonkey, the Firefox JS engine, and we do at least make sure to allocate string data in a separate part of the heap from everything else.)
People who hack JS to store arbitrary data in strings are already fighting a loosing battle, and I see no point to help them.
But my point is that we have moved from the JS as a scripting language which did not allow for arbitrary binary data, to one which did without much though over that.
Half of existing problems with zero click, zero days, and zero browse exploits running in the wild, and Chrome becoming the ActiveX 2.0 is that.
There is really no reason for a web browser to do computing on the web, and thus no need for binary manipulations in Javascript on the web.
I'm not saying to axe it from JS, but JS may limit the the browser use case by a limited set of JS standard.
https://news.ycombinator.com/item?id=16312317
But yeah you could try and mangle it and represent them internally as e.g. a rope, but that's not a bullet proof solution.
In the Wasm engine inside of V8, the code is writable and executable at the same time because the JIT uses multiple concurrent threads in the background during execution and incrementally commits new JITed code as it is finished. (And, funnily enough, this performance optimization is mostly for asm.js code, which is verified and internally translated to Wasm, to be compiled and executed by the Wasm engine).
The long-term holy grail is to move the JIT compiler entirely to another process, so only that process has write permissions, and the renderer process (where Wasm and JS execute) has only R and execute permissions, and they used shared memory underneath.