Securing Firefox with WebAssembly
hacks.mozilla.org
hacks.mozilla.org
I'd love to do the same for our contenteditable implementation. The hard part here is to implement a DOM abstraction, because that code currently pokes at DOM objects directly and you can't safely do that across a wasm barrier. Once we've done that, though, Firefox's contenteditable implementation would become a cross-browser library, which opens up some interesting opportunities. We could use it in Servo, and authors could ship it on their Web pages if they want to ensure a consistent contenteditable experience across browsers.
I guess maybe you could make an attribute which just enables a flashing cursor, and then everything else could be done with DOM apis...
Do you happen to have either or both implementations on the public internet? If so, I could see just how many seconds it takes me to be infuriated by them, especially by the non-contenteditable text editor. If I fail, I will gladly eat my metaphorical hat, but presently I would assign odds of well under 0.1% of that happening.
Sure, contenteditable has many bugs and inconsistencies, and Chrome’s implementation especially is a toy as regards functionality (e.g. poor table and image handling, difficulty with distinguishing a caret inside the end of one node from one after the end of that node), but much of the 60% that it gets you is stuff you can’t get at all any other way, especially insofar as it varies by platform, mostly deliberately.
pcwalton’s proposal interests me because it would actually concretely examine what can and can’t be done, and definitely identify the shortcomings. It would have a chance of actually being good.
I don't know about this. Google Docs isn't great (I haven't used Paper), but CodeMirror (https://codemirror.net/) is excellent. Performance is flawless. All the platform shortcuts + extra niceties like multiple cursors.
CodeMirror is rather good as such things go. Last time I tried it it had serious issues with some keyboards on Android (regardless of browser, I believe), but that looks to be working well now. Well, either that or the new Firefox for Android has worked around the input problems; could be either, I don’t have a URL that I know was broken and hasn’t been updated recently.
But even so, it still has problems, some niggling and some major. Navigation keys don’t behave natively (e.g. on Windows, select a range and then press Up or Down and it should go up or down one line from where the caret is, but instead Up takes you to the start of the selection and Down to the end). I can’t get a caret thumb on Firefox on Windows, and it seems very hit-and-miss on Android, and the Samsung keyboard on Android is going crazy with its suggestions as you move the caret around the document—and that’ll be basically because of my next point.
Perhaps most seriously, it’s completely unusable from the perspective of accessibility tech. And most damningly, guess what the solution to that is? They’re working on CodeMirror 6, and concerning accessibility https://codemirror.net/6/ says:
> This version leaves more to the browser, instead of “faking” the editing process in JavaScript. This makes it more transparent to screen readers and other accessibility tools.
You know what “leaving more to the browser” means?
contenteditable.
Yep.
It still interferes with various native user agent functionality (e.g. navigation keys are still wrong and it’s still interfering with caret thumb and long press on at least Windows), but it’s distinctly better because it reduces the amount of the important type of cleverness.
Believe me, I know. I did my own once upon a time (back when IE6 was still a thing, and supporting IE-style ranges was required!). How do you deal with things like the caret if you're rolling your own. Just fake it with a div?
Only if you ignore inconvenient but important things like internationalization and accessibility.
This might be an advantage for startup performance, but it's also a disadvantage performance wise as then you can't use all available features of the CPU. That's one of the advantages that wasm gives you.
> we were often asked, “why do you even need this step? You could distribute the wasm code and compile it on-the-fly on the user’s machine when Firefox starts.” We could have done that, but that method requires the wasm code to be freshly compiled for every sandbox instance. Per-sandbox compiled code is unnecessary duplication in a world where every origin resides in a separate process.
Android keeps an on-disk cache, performing native compilation at installation time, or at first startup after an OS update. One could have a similar cache for Firefox as well.
Anyways, this stuff can be improved in the future as well. This doesn't change the fact a bit that it's an amazing and really great idea to improve safety of the browser. I love it!
If you’re describing what I think you’re describing, that was a Dalvik thing (Android 4.4 and earlier), which ART (Android 5 onwards) doesn’t do. I also found it a pain, because from time to time even when there hadn’t been an OS update or any other such change my phone would take three or four minutes longer to boot up as it decided it had to optimise all its packages. No idea whether that was a typical experience.
This is such a good and almost a "oh, duh" moment. They can significantly decrease the attack surface simply by aggressively sandboxing everything.
The fact that it may even be faster due to the possibility to JIT in platform specific optimizations is really gravy.
Implementing the wasm vm and its basic apis would be simpler in a new operating system. Because the way it is now, the web browser itself is more complex that writing a simple operating system. That hinders innovation in the Operating System space.
https://blog.stackpath.com/webassembly/
It doesn't seem terribly unlikely. I don't think it's the goal, but it seems like a fairly likely outcome.
Language environments and containers.
Please, please don't do that. Tk is completely inaccessible to blind people via screen readers, and probably people with some other disabilities as well, on all platforms. Most toolkits written by people who decide to throw out those messy web standards would probably have the same problem.
Maybe you are really good at this.
But for a good chunk of software engineers AFAIK compiling Java to bytecode and running it on the JVM easily outperforms their optimized code performance wise in most cases.
JVM and JDK writers (and the same people on the Dotnet side) aren't dimwits and their efforts over the last two decades are being applied every time we compile and run software on their platforms.
On the contrary, I for one enjoy the benefits that the JVM brings to my poorly-optimized bytecode produced by javac.
For a language whose compiler already outputs safe binaries, this step would be redundant.
It's not that easy to write a safe compiler though. Would a compile toolchain that uses WebAssembly for all compilation be useful?
The big difference is that the WASM sandbox significantly reduces the surface area of what bad stuff can be done.
Today, a compromise in the browser means the attacker can do whatever the browser can do (which is usually a LOT). With the sandbox, a compromise can only really affect what the sandbox has available to it. That means, if your sandbox only exposes a single method which takes in a string and returns a string, the worst thing an attacker can do is return a malformed string.
Of course, if you mishandle that returned string then bad stuff will happen but it's a far cry from the input string being able to potentially cause arbitrary code execution which installs a virus on your machine.
To really do something evil you have to not only compromise the code running in WASM, you have to find a way to break out of WASM. That's a lot harder to do.
Alternatively WASM could eventually support memory tagging like SPARC and ARMv8.
For example, a WASM based security module can just start logging-in everyone as admin, because the user metadata got corrupted.
Nobody is surprised that an exploit in the authentication module can be used to log in as admin. It is different if an exploit in the font rendering module lets you log in as admin.
They are just two (equally important but) orthogonal facets of security
It seems like there is some kind of cross-module memory protection? Maybe Erlang would be an interesting comparison?
And you can pass callback functions to sandboxes, which IDK if you can do with separate processes. Does process-level sandboxing provide any advantages WASI doesn't?
[1] https://github.com/bytecodealliance/wasmtime/blob/master/doc...
[2] https://github.com/bytecodealliance/wasmtime/blob/master/doc...
Personally, if I had to design a solution for this problem, I would use the io_uring model - which would allow every part to reside in its own process and memory space.
Safe rust solves the memory safety problem. However, there is still the possibility of a logic bug causing rust to touch something it shouldn't.
The sandbox approach is about adding a second level for malicious code to bypass. You now not only need to find a way to get past the code, you also need to find a way out of the sandbox.
It's a little like running your apps on a server with highly restricted permissions. You do that so the app compromise limits what is exposed.
WASM is really the greatest thing, but it's lacking proper support from compilers. Binaryen seems like a beast to use. I don't really understand why WASM is not just supported natively directly by clang or gcc.
Binaryen is an optional optimizer that you can run on the emitted wasm, to make it smaller (either manually, or a toolchain may integrate it for you, like emscripten or wasm-pack).
I mean it is still under development but I think it is usable. Here's a quick intro I found some time ago: https://dassur.ma/things/c-to-webassembly/
We wouldn't have been able to put wasm in Firefox like this if there wasn't decent compiler/runtime support via the clang ecosystem.
The Rust code, by contrast, slurps up the entire file contents into a buffer before writing it out. If someone is going to write code that way why even bother with a low-level language? (This "memory is infinite" mentality is something I've noticed in other Rust projects, even major ones like mio.)
Beyond that, that file is just a simple example for showing how to work with the toolchain and the sandbox.