What is fundamentally wrong about the modern Web?
Published: 2021-04-27 16:25:42

If you are in the web development business, you might think this post is about Webpack and friends. Nope, it's even more fundamental.

TLDR
----

Web as a platform is trying to solve an application containerization problem, but the way of solving it - rewriting every piece of code in the world using the "Web API" is extremely dated. Instead, Web should rely on OS-level containerization and create a common standard of interoperable native calls between different languages (something like [IDL](https://en.wikipedia.org/wiki/Interface_description_language)).

The problem
----------

Being a programmer, I'll use a 3rd party ~~library~~ blog post to describe the problem I mention in the title. [Please return after reading it](https://drewdevault.com/2020/03/18/Reckless-limitless-scope.html).

**TLDR** the key citation: *"The number of W3C specifications grows at an average rate of 200 new specs per year, or about 4 million words, or about one POSIX every 4 to 6 months. How can a new team possibly keep up with this on top of implementing the outrageous scope web browsers already have now?"*

Lets try to analyze this problem.

The essentials of web
----------
Web has started as a media for distribution of static content, like plain html pages without JavaScript. That's HTML 1-4 epoch.

Then people realized, that content can be dynamic, interactive. The border between the content and the application started to fade out. That's the beginning of the "modern" web, back in the days called HTML 5.

HTML 5 started as a list of improvements to HTML 4. And the more people were able to do with the modern Web, the more things they wanted to do. The improvements list became endless and this is where we are currently.

But why has the Web become so popular as a media for distributing interactive content (aka applications)? There are regular desktop applications, you can download and run on your computer. Multiple good reasons, I'll mention just few:
- Security. Obviously, running some untrusted code on your machine, you can easily find yourself sending bitcoins to someone, to decrypt your HDD with you work files. Or discover your business-critical files published on every torrent tracker.

Web acts here as a *virtual machine* (**Web VM**), which sandbox the application and limit the potential harm. In practice this point does not hold, web browsers are still the most common vector of malicious software infection.
- Interoperability. Instead of writing your application for all possible CPU architectures, you write it for "Web VM".

I'll focus on the security problem below, as most important one, after all, even C++ programs can be cross-platform nowadays.

Web as a virtual machine
-----------------

The main purpose of the Web VM is provide a secure sandbox, to be able to run the arbitrary untrusted code. 

When you open a page with the weather forecast, nowadays it might be showing some 3D scenes of Earth+Moon orbits and whatnot. You do want those 3D scenes, they are very informative. 

The real trouble might begin when you'll decide to check that link, your colleague send to you with a note, like "check out this awesome video". You are curious about the video, but you don't want your machine to be polluted with viruses.

So, you want a combination of security and versatility in the same time. Why an endless list of extensions and new specs is needed for the Web VM to provide both? 

Because its a closed environment - every new use case or feature requires a new specification, even that already established solutions/libraries exists for it, in the "native" code.

Internal demons
-----------------

Looking from the other viewpoint, the so called "modern Web API" is just a normal wish of every programmer - to rewrite every piece of software in the world in their favorite language/framework, instead of solving the business requirements.

It is an intrinsic desire of every developer - "I'll rewrite that neat library doing feature X, but I'll do it in the right way, using tabs instead of spaces, or may be, 2 spaces instead of 4, or may be, I'll properly insert semi-colons after every statement, or, I'll remove those noisy semi-colons after every statement, or, I'll use an awesome Web API instead of that C++ lib, *please insert your favorite preference here*"

In case of Web VM, this desire is also supported by the rational explanation - "I can't use a library for this purpose - it might be not secure. What is forgotten - "I can't use that native library for this purpose, because WebVM does not support native code".

Providing a secure application sandbox is a real-world need. Rewriting everything from scratch - internal demon.

Security, done right
-----------------

Again, being a developer, I'll use a 3rd party content to demonstrate, why the current Web VM approach to security is not correct.

Check out this [thread in Node.js mailing list](https://groups.google.com/g/nodejs-dev/c/9vApf6IvRxk/m/6rOlU-OyQe4J)

Someone is submitting a PR for the "node-safe-mode" ("hardened" node), that should allow *"running third-party-written code"*. The list of improvements includes:
* *Each node processes will be given a file system directory, which will contain the JavaScript it runs, ... other than that, the process will have no access to any other part of the file system* 
* *Each node process creates a socket that it uses to receive requests from the server.  To prevent different node processes from communicating with each other directly, the ability of node processes to connect to sockets will be restricted.*
* *On general principles, Node processes will not be allowed to kill other processes, change their default directory, change their effective user or group id*
* etc..

**Wow, this looks pretty much like the security guarantees of the regular web page.** Must be an excellent addition to the Node.js! Ok, what are the answers to this generous contributor?
____
*"No. I appreciate the effort but it sounds too much like PHP's safe mode and everyone knows how broken that is. Containerization should be done at the OS level, not the application level."*
____
*"The problem with continually restricting things like child processes and native addons, is that these are popular features, and you still face problems like port/fd hijacking. ... In order to prevent fd attacks and port hijacking ... you would want to completely restrict the C++ level access instead of Javascript as well...*
____
*... I recommend VM level separation if you are serious about security combined with OS level protection"*
____
*"True security containment is not trivial. It's not a feature you add onto a platform later. It's something that you really have to bake into the architecture from the very start, and evaluate all your trade-offs in that light. .... Furthermore, doing multi-tenancy in this way is extremely dated, and unnecessary. There's better technology now."*
____
Wait, what? A non-trivial PR, which adds a security model to Node, that is similar to a web page security model, is rejected, because *"doing multi-tenancy in this way is extremely dated"* and *"there's better technology"*? 

Pretty much all those who replied to the PR, said that doing security at the application level is old, unreliable way, which also restricts the "native addons". Then why Web is still using such old-fashioned approach?

If we combine the citation from one of the replies from the Node.js thread, with the citation from the blog post I mentioned in the beginning, we'll receive exactly the problem, the modern Web is experiencing:

**"The problem with continually restricting things like child processes and native addons, is that these are popular features, and your specification starts to grow at the speed of one POSIX every 4 to 6 months"**

Solution
--------

The solution is dumb simple. As suggested by Node.js engineers, Web should provide native, OS-level containerization for the pages. Yes, every tab in your browser should run in container. If you recall, when Chrome started running every tab in a separate process, that seemed like something inconceivably new and even frightening. Well, that has proven itself as a reliable solution.

The next step is to put every of those processes into separate OS-level container. That's just it - you have the proper, real, security for the untrusted code, and that code can use "popular native addons". 

There's no need to write a spec for every library in the world. Especially if those specs are just descriptions of the imperative interfaces, not the formally-verified code.

Need to mention that "web page as a container" is not a new concept. There were already similar attempts, like [Java Web Start](https://en.wikipedia.org/wiki/Java_Web_Start). They were, however, application containers, similar to the "safer-node". The missing piece was OS-level containerization. 

Vision
------

Lets imagine we have this OS-level containerization for web pages and page can be running native code easily. How the Web will look like in this brave new world?
___
The role of the JavScript and HTML/CSS will probably reduce somewhat. The WebAssembly hype wave will not be that big, or not happen at all. However, WebAssembly is moving in the right direction, for example with InterfaceTypes proposal.
___
The notion of desktop application may start disappearing, why would anyone write a program limited to only one CPU architecture? For example, I imagine all kinds of various editors which are currently desktop applications (like PhotoShop, 3DMax, etc) will have "web" equivalents.
___
It should be possible to run a whole OS desktop in the web page. I imagine, if I had to open some *really* untrusted page, I'd be using a browser, running inside of such "Web OS" page, to provide an extra level of containerization. Containers may have different virtualization mechanisms - from being a container as we know now, to being a VM emulator (supposedly more secure).
___
The border between the web page and mobile application will disappear completely. This is probably not what the owners of the "mobile app stores" want. 
___
The key piece of the puzzle for this paradigm shift to happen, is providing the really secure containerization solution. The only way of doing it is writing as formally verified code.
___
The IOT can benefit from the secure execution sandbox/container a lot. Imagine various devices, too dumb to visualize their interface, but smart enough to upload it to your computer/smartphone for execution. No need for "cloud", every "internet-thing" can carry all needed software onboard.
___
The need for formal spec for every use case will reduce a lot. Instead, the need for the robust, mathematically sound, native code interoperability will appear.
___
A web page and a desktop application window - these are the equal concepts.


Conclusion
-----------
If we look at the Web from a bit more general perspective, we can replace the "web page" concept with the "web node". A universal execution node, combined with other nodes in a distributed network and able to the run untrusted code - this is what probably Ryan Dahl had in mind back in the days, calling his project "Node". 

Hopefully the argumentation in this post is straightforward enough. I believe OS-level containerization is a next logical step in the Web evolution.