Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I'm bit surprised that browsers did not get a mention here. They are one of the big examples of how an application can be split into gazillion small processes, split along trust boundaries, while also being pretty performance sensitive applications.

As for transitive deps, I have some hopes for more "distro" like models to arise. In particular I see clear parallels in how traditional Linux distros work and how large faang style monorepos work. So maybe we could see more these sort of platforms/collections of curated libraries that avoid these deep transitive dep trees by hoisting all the deps into one cohesive global dependency that has at least some more eyes on it.



I think Chrome isolated processes fail the idealized criteria, though:

> 1. Performance. [...] Unix-esque shared memory, though much faster, is far too difficult to use reliably for untrusted components.

> 2. Expressivity. [...] without descending into the horrors that RPC (Remote Procedure Call) tends to descend to.

Author is asking for how can we do better / get this popular and used all over, not what's the current state of the art (when that SOTA is a notoriously large and complex program that your average programmer has never looked inside of).


Yes, and Chrome's Mojo IPC system is actually one of the only parts of the codebase that's neatly factored out (somewhat) into a reusable library.

https://chromium.googlesource.com/chromium/src/+/master/mojo...

In the past I used the Java SecurityManager to do a PoC PDF renderer that sandboxed the Apache PDFbox library. I lowered the privilege of the PDF rendering component and tested it with a PDF that exploited an old XXE vulnerability in the library. It worked! Unfortunately, figuring out how to do that wasn't easy and the Java maintainers got tired of maintaining something that wasn't widely used, so they ripped it out.

There are some conceptual and social difficulties with this kind of security, at some point I should write about them.

1. People get distracted by the idea of pure capability systems. See the thread above. Pure caps don't work, it's been tried and is an academic concept that nothing real uses but which sucks up energy and mental bandwidth.

2. People get distracted by speculation attacks. In process sandboxing can't stop sandboxed code from reading the address space, so this is often taken as meaning everything has to be multi-process (like Mojo). But that's not the case. Speculation attacks are read only attacks. To do anything useful you have to be able to exfiltrate data. A lot of libraries, if properly restricted, have no way to exfiltrate any data they speculatively access. So in-process sandboxing can still be highly useful even in the presence of Spectre. At the same time, some libraries DO need to be put into a separate address space, and it may even change depending on how it's used. Mojo is neat partly because it abstracts location, allowing components to run either inproc or outproc and the calling code doesn't know.

3. People get distracted by language neutrality. Once you add IPC you need RPC, and once you add RPC it's easy to end up making something that's fully language neutral so it turns into a fairly complex IDL driven system. The SecurityManager was nice because it didn't have this problem.

4. Kernel sandboxing is an absolute shitshow on every OS. Either the APIs are atrocious and impossible to figure out, or they're undocumented, or both, and none of them provide sandboxing at the right level e.g. you can't allow a process to make HTTP requests to specific hosts because the kernel doesn't know anything about HTTP.

Sandboxing libraries effectively is still IMHO an open research problem. The usability problems need someone to crack it, and it'll probably be language/runtime specific when they do even if libraries like Mojo are sitting there under the hood.


> People get distracted by the idea of pure capability systems. See the thread above. Pure caps don't work, …

I’m one of those “distracted” people who has never gone far enough with a capabilities-based language to figure out why they don’t work.

I read a lot about E and tinkered with Pony, and it seems that the biggest barrier is bootstrapping/network effects (e.g. lack of available libraries & expertise) rather than something intrinsic to a capabilities oriented security model.

In contrast, I only just learned about Javas SecurityManager from an earlier comment on this post. Reading the documentation at https://docs.oracle.com/javase/8/docs/api/java/lang/Security... leaves me with an impression of more complexity for integrators (as you noted) and a need for vigilance at system boundaries by runtime implementors. Building on reference capabilities seems much much simpler, but maybe that’s just my lack of experience ?

> There are some conceptual and social difficulties with this kind of security, at some point I should write about them.

I guess my comment is a long way of saying: please do!


The SecurityManager actually was a capability system! It just wasn't a pure capability system. Instead, capabilities enabled finer grained permissioning and optimization, which is IMO usually the right way to use them.

The problem with a pure caps system is that basically all software expects to have some ambient permissions. Changing that assumption not only breaks every API of every library, but reduces the usability by a lot too. For instance, it's commonplace for libraries to support tweaks to their behavior via environment variables or (in Java) system properties, but, those could also contain secrets, so that has to be a permission. In a pure capability design there's no way to grant a library the permissions it needs statically, instead a higher privileged component has to either do the read itself and pass the answer to the lower privileged part, or wrap its power into a capability object that exposes only what's needed. But then who writes that object? It's boilerplate so it'd make sense for it to come from the library itself, but, oh, that doesn't work because it's that code that's enforcing the security boundary. The user of the library has to write the code (or copy/paste and review it).

The SecurityManager design had some flaws but was basically a correct design for sandboxing most libraries (those that can't exfiltrate data obtained via side channel attacks):

1. You could assign libraries static sets of permissions, or not.

2. You could build strong capabilities using a mix of taking away a libraries reflection permissions, and AccessController.doPrivileged which terminated the intersection stack walk.

For instance, imagine a library that reads a config file (e.g. for logging configuration). There are two ways to handle this. You could change the library API so it requires a file capability. Java lets you do that - File[Channel] are capability objects. But, this is tedious for the developer. Now to use the library they have to write boilerplate to open the config file themselves so they can pass the opened capability in, which in turn means that basics like the location of the file can't be encapsulated in the library itself.

Alternatively you can just ship the library with a permissions file written in a simple DSL, that has a line like

    grant my-lib open ~/.config/my-lib/logging.json
Now the library API doesn't have to change, the developer doesn't have to open the file for the library, and the permissions can evolve alongside the evolution of the logging feature itself. The library user only has to review the permissions file when it changes, if they care about sandboxing, or ignore it if they don't.

This is much more usable! Capabilities in this model are still useful, but are the preserve of some special cases. For instance, complex permission checks can be done once and then encapsulated into a capability object (this is how file capabilities work, all the authorization logic is only on the open path and calling read or write is a much cheaper check). And of course APIs can be extended smoothly to support this, any time you have an API like:

    void setConfigFilePath(String path);
you add another method

    void setConfigFile(File file);
and make the first version delegate to the second. Now the library can have its permissions removed and be given a file capability instead, if that makes more sense.




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: