> How do you run Turing-complete code which might be hostile?
That's the key problem that (almost) nobody wants to talk about. We've been trying to solve the decision problem for a long time, and we already know that even relatively simple problems are provably undecidable[1]. Any real program will be much more complex[2]. An unknown program could generate any output it wants and we cannot know that without running it.
The only solution is to remove output methods. If a program can only e.g. draw to a framebuffer without the ability to trigger future network activity, the worst it can do is waste CPU & RAM. Allowing literally any interface to generate network activity (even indirectly) and people will find ways to tunnel data over that interface.
The original design for the web was (probably) safe. It didn't require anonymous Turing complete code, and provided quite a bit of functionality with declarative markup. It even allowed simple (but still useful) server-side applications with 3270-style forms (again, no code needed). This was wonderfully useful, reasonably safe, and most importantly it was understandable by both humans and machines.
Today's web requires trusting a new set of undecidable software on each page load. We're supposed to trust 3rd parties even though trust is not transitive. We're supposed to accept the risk of running 3rd party software even though risk is transitive. Without some sort of miraculous total reversal where browsers revert back to pre-javascript days, this is going to end badly.
[1] https://www.scottaaronson.com/blog/?p=2725
[2] If your program uses >7918 Turing machine states, [1] proves that it's behavior cannot be analyzed by ZF set theory.