For example, why don't more languages allow me to say, "This XML parser is forbidden from talking to the network or file system"?
Because that's not up to the programming language to decide. In which context a particular piece of code is executed is out of scope for the design and compilation phase of your program -- that's part of the application deployment, and that deployment is usually not written in the same language as your program.
What you're asking for is basically the microkernel approach applied to applications: each microservice has its own capabilities and data access, and control is passed through RPC. This exists, and it can be implemented in any language (though more readily in some than in others), but this is not a programming language feature: it's a runtime feature that must be provided by the environment (whether JVM, Linux, Docker, SeL4 or browser) in which your code is deployed.
> Because that's not up to the programming language to decide.
There's actually a lot of really neat research in this space, including:
- "Row types" for effect systems, which allow the compiler to cleanly keep track of what code has access to what parts of the outside world.
- Capability systems, where you essentially need "handles" to access things in the outside world.
- Strong-typed unikernals, which use either of the above approaches to replace the process boundaries in a regular microkernel.
Admittedly, none of this is exactly ready for the mainstream yet. But there are plenty of ways to help address these issues at the programming language level. And I think this is worthwhile, because as the Chrome team has pointed out several times, trying to stick every parser in a seccomp-isolated process is a lot of hard work. And it rarely gets done in practice.
Given the sheer number of dependencies many projects have the days, and the growing number of "supply chain" attacks against libraries, I think this is worth all the effort that's going into right now.
Maybe in 10 or 20 years, we'll see some commercially-acceptable languages that explore this space.
Because that's not up to the programming language to decide. In which context a particular piece of code is executed is out of scope for the design and compilation phase of your program -- that's part of the application deployment, and that deployment is usually not written in the same language as your program.
What you're asking for is basically the microkernel approach applied to applications: each microservice has its own capabilities and data access, and control is passed through RPC. This exists, and it can be implemented in any language (though more readily in some than in others), but this is not a programming language feature: it's a runtime feature that must be provided by the environment (whether JVM, Linux, Docker, SeL4 or browser) in which your code is deployed.