I think a really useful piece of information here is why did the Java SecurityManager fail. People talk about sandboxing library code but this is literally what the SecurityManager made possible ages ago. But virtually zero applications make widespread use of the SecurityManager to isolate library code.
Was it a question of being too soon? Was it horribly un-ergonomic (this is the explanation I usually hear)? Did its features not actually match what developers need?
It feels like callstack based permissions are a natural solution to "holy shit my json deserialization code is deleting files on disk" but there clearly is some trap hidden here that caused old solutions to fail.
Short-term: The only way out of this is to review + whitelist every package before it hits the NPM registry. This is something my company is building and we did a write up about it (and Node-ipc) here[0].
Longer term answer: Something like Deno needs to take off that adds permissions per dependency. We need to sandbox all untrusted code by default.
0: https://www.lunasec.io/docs/blog/node-ipc-protestware