jerf a day ago

If anything is going to put capabilities into the programmer ecosystem, I think it's this problem.

The neat thing about this particular problem is that you can do some really coarse things and get some immediate benefit. Capabilities in their original form, and perhaps their truest form, carry down the call stack, so that code can do things like "restrict everything that I call can only append to files in this specific subtree" in the most sophisticated implementations. But you could do something more coarse with libraries and just do things like "These libraries can not access the network", and get big wins on some simple assertions. If you're a library for turning jpegs into their pixels, you don't need network access, and with only a bit more work, you shouldn't even need filesystem access (get passed in files if you need them, but no ability to spontaneously create files).

This would not be a complete solution, or perhaps even an adequate solution, but it would be a great bang-for-the-buck solution, and a great way to step into that world and immediately get benefits without requiring the entire world to immediately rewrite everything to use granular capabilities everywhere.

  • jonahx a day ago

    Capabilities are the only way.

    It is insane to me that in 2025 there is no easy way for me to run a program that, say, "can't touch the filesystem or network". As you say, even a few simple, very coarse grained categories of capabilities would be sufficient for 95% of cases.

    • zokier a day ago

      systemd-run inherits afaik all the extensive sandboxing features from systemd

      https://www.freedesktop.org/software/systemd/man/latest/syst...

      https://www.freedesktop.org/software/systemd/man/latest/syst...

      sure, the command line get bit verbose but nothing that an alias or small wrapper couldn't solve

      the big problem is that modern operating systems have huge surface area and applications tend to expect all sorts of things, so figuring out what you need to allow is often non-trivial

    • taeric a day ago

      I'm curious what all you want to run that you don't want to access the filesystem? Or the network?

      Like, I get it for a few things. But it is a short path to wanting access to files I have created for other things. Pictures and videos being obvious files that I likely want access to from applications that didn't create them.

      Similarly, it is a short hop from "I don't want any other application to be able to control my browser" to "except for this accessibility application, and this password management application, and ..." As we push more and more to happen in the browser, it should be little surprise that we need more and more things to interact with said browser.

      • jonahx a day ago

        I think you misunderstood. Among the coarse grained capabilities I mentioned would be "access to folder X and it's subfolders" (read or write).

        But to answer your question there are, eg, tons of programming packages in any language that I want purely for their computational abilities, and I know this for certain when using them. In fact for the vast majority of GUI programs I use, or programming packages I use, I know exactly what kind of permissions they need, and yet I cannot easily restrict them in those ways.

        • taeric a day ago

          It is specifically running applications that always trips me up here. As a user/operator of the computer, I have been bitten by applications being too locked down for them to be useful in the past. I /think/ we have gotten better such that it is easy to have better OS behavior when it wants to restrict an application. But specifically sandboxing by default has been a source of terrible application behavior for me, in the past. Is a lot like using a shadow banned account where everything looks correct, but nothing is actually showing up. Very confusing.

          Now, I think your point on restricting the libraries that are imported to a program makes a ton of sense. I'm not entirely clear where I would want the "breaker box" of what an application is allowed to do to be located, but it is crazy how much just importing some library will do in many programs.

          • yencabulator 6 hours ago

            I think this sort of stuff implies a switch to new APIs that understand that the app is inside a sandbox, instead of "just trying to do things". For example, XDG Portals for opening/saving documents, instead of open(2) syscall.

          • jonahx a day ago

            Well you are ofc free to give applications full reign if you want. But you should at least be able to say, "No, desktop calculator I just downloaded, you can't do anything but compute and draw things in your application window".

            More broadly, creating a good UI around granting capabilities is non-trivial. But that's a separate problem from simply not being able to make even the most basic kinds of restrictions that you want in most cases.

            • chii a day ago

              I think the ideas in qubes OS (https://www.qubes-os.org/) is reasonable in implementation given today's applications, and the need for backwards compatibility.

              Unfortunately, the performance is what suffers, and morse law hasn't kept up such that vm based OS can be used by the regular laymen.

            • taeric a day ago

              Totally fair. I just don't know of that many (any?) "desktop calculator" applications that people download. I'm far more expecting that people are downloading and running social applications than they are isolated things.

              Mostly fair that it would be good if we could say "on site foo.com, request for any access to not-foo.whatever that happens." I can't remember the last time I saw the sheer number of third party network accesses that happens on far too many sites. It was sobering.

              • frederikb 21 hours ago

                Oh, but they do! There used to exist a boatload of malware on Android disguised as common conscience apps, famously flashlight apps/widgets.

                As a random example, see this one ( https://www.welivesecurity.com/2017/04/19/turn-light-give-pa... ) which is a banking trojan cosplaying as a flashlight widget.

                Now there is a more or less sophisticated permission system which users then bypass by still accepting any prompt if you promise them anything shiny...

                • taeric 11 hours ago

                  Apologies, I had dropped offline.

                  I actually am less against these ideas on the phone. Quite the contrary, I think I'm largely agreed that more efforts need to be done to let people control those.

                  I am also sadly skeptical that this works, there. I've seen my family that is all too eager to just click "ok" on whatever an app says it needs. :(

              • bhelkey a day ago

                > Totally fair. I just don't know of that many (any?) "desktop calculator" applications that people download.

                Quite a few apps fall into this category: single player games, photo editors, word editors, video players, pdf editors ...

                It seems very reasonable to restrict these applications from accessing the internet.

                • taeric 11 hours ago

                  Gaming, I'm willing to largely get behind as something that should be more locked down. Networked games, of course, are a thing. Single player games should be a lot more isolated, though.

                  Any sort of editing software, though, gets tough. That is precisely the are that I have had bad experiences in in the past. Would try to edit raw photos and export them to a place I could draw or publish with them. Using a shadow banned application is the only way I know on how to describe how that felt.

      • bluGill a day ago

        Anything really. I tried to print from a sandboxed application the other day and turns out it can't be done - or at least it can't be done by "common user". As an educated person who has been using unix of all sorts I could probably figure it out, but it isn't something I should have to figure out in 2025. (it was a pain in 1998, but it worked better than the snap sandboxes of today despite the pushers of snap from an organization claiming that ease of use is important)

        • taeric a day ago

          Right, but this is largely to my point? I said in another thread that sandboxing often feels like being shadow banned on your own computer.

          I get wanting "safe" computers. I'm not clear that we can technically define what legally "safe" means, though. :(

          Now, i grant, we can probably get further than I would spit ball based on some bad interactions in the past.

          • bhelkey a day ago

            > Right, but this is largely to my point? I said in another thread that sandboxing often feels like being shadow banned on your own computer.

            > I get wanting "safe" computers. I'm not clear that we can technically define what legally "safe" means, though. :(

            You are currently using a web browser. When you go to ycombinator, the site cannot read the contents of your email in the next tab. This isn't a shadow ban you on your own machine, it's just a reasonable restriction.

            Imagine you just installed a new web browser (or pdf reader, tax software, video game, ...). It should not be able to read and send all the pictures in your camera roll to a third party.

            • lmm a day ago

              > Imagine you just installed a new web browser (or pdf reader, tax software, video game, ...). It should not be able to read and send all the pictures in your camera roll to a third party.

              But I use my web browser to upload my photos to the cloud, so it absolutely should.

              (I do somewhat agree with the general point, but I find it very funny that your very first example would break my workflow, and I do think that highlights the problem with trying to sandbox general-purpose programs)

              • theamk a day ago

                Cell phones show this can be done: you can pick individual files ot sets of files using system file picker, and that one file (and only that file!) is opened for browser.

                If it needs more, there is always "access all photos" permission, and "access all files" too.. but this is explicit and requires user prompt. And the last part ia very important - if freshly installed browser requires full files access without explanation, this is likely for spyware, so uninstall it and leave bad review.

      • BobbyTables2 a day ago

        How about “curl” and “wget” shouldn’t have free rein to read/upload and/or overwrite every damn file owned by my user?

        Why does “ping” need to have file system access?

        • yencabulator 6 hours ago

          Moving out of the world of "applications" into shell commands, we're gonna need a new shell that understands that `wget -o myfile https://example.com` needs to be handed a capability to write data, or we need change our habits a lot into always shuffling everything over pipes or such. In either scenario, if you want that level of granularity, I don't think UNIX will survive as we remember it.

          (More likely path for now: start a new sandbox, run things in it, put result files in an "outbox", quit sandbox, consume files from outbox. Also not very convenient with current tools.)

      • toast0 a day ago

        Most things you run in a pipeline don't need access to the filesystem or the network.

        Something dangerous like ffmpeg would be better if the codecs were running without access to files or the network, although you'd need a not fully sandboxed process to load the media in the first place.

        Many things do need file access, but could work well with an already opened fd, rather than having to open things themselves (although forcing that results in terrible UX).

        Of course, filesystem access gets tricky because of dynamic loading, but lets pretend away that for now.

      • tolciho a day ago

        ping(8) has no particular access to the filesystem, and can only do inet and stdio. At least on OpenBSD. I have a modified version of vi(1) that cannot write outside of /tmp or ~/tmp, nor access the internet, nor can it run programs. Other text editors could easily access ~/.ssh keys and cloud them. Whoops? sshd(8) and other daemons use privsep so that the likely to be exploited bits have no particular access to the system, only pipes off to other portions of the OpenSSH complex.

        Maybe if rsync were better designed exploits could be better contained; alas, there was a recent whoopsiedoodle—an error, as Dijkstra would call them—and rsync can read from and write to a lot of files, do internet things, execute whatever programs. A great gift to attackers.

        It may help if the tool does one thing and one thing well (e.g. the unix model, as opposed to the "I can't believe it's not bloat!"™ model common elsewhere) as then you can restrict, say, ping to only what it needs to do, and if some dark patterner wants to shove ads, metrics, and tracking into ls(1) how about a big fat Greek "no" for those network requests. It may also help if the tool is designed (like, say, OpenSSH) to be well partitioned, and not (like, say, rsync) to need the entire unix kitchen.

        Image libraries have had quite a few CVE or whoopsiedoodles over the years, so there could be good arguments made to not allow those portions of the code access to the network and filesystem. Or how about a big heap of slow and expensive formal verification… what's that, someone with crap security stole all your market share? Oh, well. Maybe some other decade.

        A non-zero number of people feel that "active content" e.g. the modern web is one of the worst security missteps made in the last few decades. At least flash was gotten rid of. So many CVE.

        P.S. web browsers have always sucked at text editing, so this was typed up in vi yielding a file for w3m to read. No, w3m can't do much of anything besides internet and access a few narrow bits of the filesystem. So, for me, web browsers are very much in the "don't want to access the filesystem" category. I can also see arguments for them not having (direct) access to the network, to avoid mixing the "parse the bodge that is HTML and pray there are no exploits" with the "has access to the network" bits of the code, but I've been too lazy to write that as a replacement for w3m.

      • groby_b a day ago

        Simple example: Third party SW in a corporate context. Maybe you want to extend some permissions to some internal sites/parts of the FS, but fundamentally, there's limited trust.

        • taeric a day ago

          This is an odd one. At face value, I want to agree. At the same time, if you don't trust the operator of the computer with access to data, why are we also worried about programs they run? If you don't trust them with access, then just don't give them access?

          I'm open to the idea that some people are locked down such that they can't install things. And, that makes a lot of sense. You can have a relationship that is basically, "I trust them with access to data running this closed set of applications." Managing system configurations makes a ton of sense.

          But, as soon as you have full trust of system management on a group, you start getting in odd worlds where you want to allow them to have full access, but want to stop unauthorized use. Which, we don't have a way to distinguish use from access for most data.

          • groby_b a day ago

            Trusting the user does not transitively extend to the software they use. You might be OK with them e.g. looking at company financials, but you'd really like to be sure e.g. that the syntax highlighter they use doesn't go and exfil that data. You still want them to be able to use the syntax highlighter. (Yes, it's an obviusly made-up example_

            You _can_ fully vet apps, each and every one. Or you can choose a zero-trust approach and only vet the apps where it's necessary to extend trust.

    • est31 a day ago
      • kybernetikos 21 hours ago

        The key requirement to solve this problem is that you can ensure that third party libraries get a subset of the permissions that the code calling them has. E.g. My photo editor might need read and write access to my photo folder, but the 3rd party code that parses jpegs to get their tags needs only read access and shouldn't have the ability to encrypt my photos and make ransom demands.

        Deno took a step in a good direction, but it was an opportunity to go much further and meaningfully address the problem, so I was a bit disappointed that it just controlled restrictions at the process level.

        • nonameiguess 12 hours ago

          Kind of two different things being addressed here. The article is talking about doing this at the granularity of preventing imported library code from having the same capabilities as the caller, which requires support from the language runtime, but the comment being responded to was saying there is no way in 2025 to run a program and keep it from accessing the network or the filesystem.

          That is simply not true. There are many ways to do that, which have been answered already. SELinux. Seccommp profiles. AppArmor. Linux containers (whether that be OCI, bubblewrap, snap, app images, or systemd-run). Pledge and jails.

          These are different concerns. One is software developers wanting to code into their programs upper limits to what imported dependencies can do. That is poorly supported and mostly not possible outside of research systems. The other is end users and system administrators setting limits on what resources running processes can access and what system calls they can make. That is widely supported with hundreds of ways to do it and the main reasons it is perceived as complicated is because software usually assumes it can do anything, doesn't tell you what it needs, and trying to figure it out as an end user is an endless game of playing whack-a-mole with broken installs.

      • IshKebab a day ago

        Deno controls access at the process level, so it's better than nothing but it doesn't really help with this specific problem. Also it delegates setting the permissions up to the user, and we know that in practice everyone is just going to --allow-all.

    • dooglius a day ago

      Can do this with Qubes OS by running in a non-networked qube

    • daveguy a day ago

      Doing this at the program level is implemented in Linux by SELinux, which defines mandatory access controls (aka limitations on capabilities). This was difficult to get right by default and make a smoothly functioning distro with policies enabled. But it is enabled by default in Fedora.

      https://en.m.wikipedia.org/wiki/Security-Enhanced_Linux

      To enable this at the programming level would require an enforcement mechanism at the level of a language VM or OS. It would require more overhead to enforce at that level, but the safety benefits within a language may be worth it.

    • IncreasePosts a day ago

      bubblewrap?

      • jonahx a day ago

        Nothing in the container space would qualify as "easy" for me. I am talking about native OS features. Also linux only (afaik)...

        Or even, for that matter, some sane capabilities for browser extensions.

        • BeefWellington a day ago

          SELinux!

          Half jokes aside, I'd love to be able to have a decent mobile style permissions experience on browser extensions and desktop apps.

    • fsflover a day ago

      > in 2025 no easy way for me to run a program that, say, "can't touch the filesystem or network".

      Qubes OS exists for more than 10 years already. My daily driver, can't recommend it enough.

      • jazzyjackson a day ago

        Windows pro also has a sandbox that can disable filesystem and network access, but they wasted the opportunity by allowing only one sandbox process at a time.

  • Veserv a day ago

    That is almost the exact backwards way to talk about capabilities. It is not about "restricting" access, it is about "granting" access.

    "These libraries can not access the network." No. "These libraries have not been given access to the network (and by default none are given access)."

    From an implementation perspective, this is just passing in access rights as "local" resources instead of using "global" resources. For instance, it is self-evident that other code can not use your B-Tree local variable if you did not pass a reference to it to any called functions (assuming no arbitrary pointer casts). You just do the same with these "resources". It is just passing things to functions instead of relying on globals. The only difficulty is making these actions/resources "passable", which is trivial at the language-level, and "fine-grained/divisible" to avoid over-granting.

    • jerf 15 hours ago

      Clearly these things are dual and you can easily model them either way, and indeed, should think about them both ways.

  • marcosdumay a day ago

    Just to say, but You are describing an effect type system. (Or, to the "types are static" people, possibly a dynamic effect system.)

    Capabilities taken literally are more of a network thing (it's how you prove you have access to a computer that doesn't trust you). On a language, you don't need the capabilities themselves.

    • justinpombrio a day ago

      You can do a lot with capabilities at the language level, if the language supports it. It doesn't require effect types: it's extremely boring from a type system perspective, which is an advantage.

      Imagine these changes to a language, making it "capability safe":

      - There is a `Network` object, and it's the only way to access the network. Likewise, there's a `Filesystem` object, and it's the only way to access the file system.

      - Code cannot construct a `Network` or `Filesystem` object. Like, you just can't, there's no constructor.

      - The `main()` function is passed a `Network` object and a `Filesystem` object.

      Consider the consequences of this. The log4j vulnerability involved a logging library doing network access. In a capability safe language, this could only happen if you passed a `Network` object to the logger, either in its constructor or in one of its methods. So the vulnerability is still possible. But! Now you can't be surprised that your logger was accessing the network because you gave it the network. And a logger asking for network access is sufficiently sketchy that log4j almost certainly would have made network access optional for the few users that wanted that feature, which would have prevented the vulnerability for everyone else!

      I talked about there being a single monolithic `Filesystem` object. That is what would be passed into `main()`, but you should also be able to make finer grained capabilities out of it. For example, you should be able to use the `Filesystem` object to construct an object that has read/write access to a directory and its subdirectories. So if a function takes one of these as an argument, you know its not mucking around outside of the directory you gave it.

      Capability safety within a language is stronger than the sort of capability safety you can get at the process level or at the level of multiple machines. But we want those too!

      • yencabulator 6 hours ago

        In theory Rust where you don't allow unsafe can do that. (Reality is not perfect: https://github.com/rust-lang/rust/issues/25860)

        Theseus OS is a research project that created single address space kernel that loads dynamic libraries written in safe-only Rust as "untrusted entities". Compiled with a trusted compiler that forbids unsafe. If they have no access to unsafe, and you're not giving them functions to link to that would hand them these a-capability-if-you-squint objects, they're supposedly sandboxed.

        https://www.theseus-os.com/

      • gnafkcud a day ago

        this was the original approach for Java, and the main idea behind being able to ship untrusted apps directly to the user and run them in the browser

        tomcat also gave different privilege levels to different parts of the classpath

        nice idea, but didn't seem to work in practice

        • justinpombrio a day ago

          That's what I'm calling capabilities at the application level (where you say "this .jar can't access the network"), rather than at the language level (where you say "this function wasn't given access to the network as an argument"). I don't think any widely known language has tried capabilities at the language level. (The language not widely known that does it is E.)

          The real power will come when you can mix them. In one direction, that looks like `main()` not getting passed a `Network` object because the ".jar" wasn't granted network access. In the other direction, that looks like the system C library you invoked failing to access the network because when you invoked it from Java you failed to provide a `Network` object, so it was automatically sandboxed to not be able to access the network.

          • tlavoie a day ago

            Have you looked at "Emily" language at all? Same person or two, their original paper isn't reachable at their linked URL, but is on the Wayback Machine. "How Emily Tamed the Caml" - https://web.archive.org/web/20221231184748/https://www.hpl.h...

            Emily took the approach of restricting a subset of OCaml, which they were running on Windows machines. No idea how tough it would be to get it running on a modern version.

            Also for OCaml, the MirageOS unikernel is neat - develop on Linux etc., then recompile configured as a virtual machine with only the drivers (network, filesystem) needed by that one app. - https://mirage.io/

          • blibble a day ago

            > That's what I'm calling capabilities at the application level (where you say "this .jar can't access the network"), rather than at the language level (where you say "this function wasn't given access to the network as an argument")

            it wasn't, it was done at the type and classloader level

            have a read about SecurityManager

      • marcosdumay a day ago

        > this could only happen if you passed a `Network` object to the logger

        Yeah, this is not only an effects type system, it's a static effects type system.

        • justinpombrio a day ago

          No it's not. I'd guess you're imagining a type signature like this one?

              void effect:Network my_function_to_connect_to_server() {
                  ...
              }
          
          I mean a type signature like this one:

              void my_function_to_connect_to_server(Network network) {
                  ...
              }
          
          Where there's absolutely nothing special about the Network type, except that (i) it has no constructor, and (ii) nothing in the Java language lets you talk to a network without it. All of this is expressible with Java's type system today.
          • marcosdumay 16 hours ago

            > void my_function_to_connect_to_server(Network network)

            See how there's the Network right there on the type?

            • justinpombrio 13 hours ago

              That's an ordinary argument type. Like:

                  void my_function_to_connect_to_server(
                      Network network,
                      int port,
                      String server_name
                  )
              
              It's not categorically different than the other arguments, and doesn't require an effect type system.

              At this point I'm not sure if you're misunderstanding what I'm proposing, or if you don't know what an effect system is. If you care to communicate, you'll need to say something more substantial. Walk me through what you're trying to say.

              • marcosdumay 10 hours ago

                Make it generic, with some kind of Resource interface that Network is one of the implementations¹, and you get a dynamic effect system.

                But that thing you wrote is a static effect system. Having a singleton that you need to carry with the type doesn't make it not part of the type system.

                1 - Or actually use Resource as a class. But Java wouldn't do this.

                • yencabulator 6 hours ago

                  I think you're talking about what power a type system needs to say that this function doesn't have undesirable side effects, while Justin is saying if you can't just "import std.net" and access the network by side effects (and can't make raw syscalls either, or poke around in raw memory), and nothing hands you a Network value, a plain old boring type system is enough.

                • justinpombrio 9 hours ago

                  Thank you for the clarity.

                  > But that thing you wrote is a static effect system.

                  The thing I wrote is expressible in Java's type system as it is today. So you're saying that Java has a static effect system?

    • jonahx a day ago

      > Capabilities taken literally are more of a network thing (it's how you prove you have access to a computer that doesn't trust you). On a language, you don't need the capabilities themselves.

      You may be thinking of the term in a different context. In this context, they are a general security concept and definitely apply to more than the network, including languages:

      https://en.wikipedia.org/wiki/Capability-based_security

      http://habitatchronicles.com/2017/05/what-are-capabilities/ (this is a great article)

      https://www.ponylang.io/

      etc...

      • bluGill a day ago

        > On a language, you don't need the capabilities themselves.

        Why not? Sometimes I want that. Just today I was looking at some code and realized that it was being used by groups that shouldn't. The code needs to be there and is great for the correct users, but someone is going around our architecture and we didn't notice it.

        • jonahx a day ago

          You are replying to the wrong post. I was quoting the GP.

    • wyago a day ago

      Effect typing can achieve capability security statically, but I've also frequently seen capabilities used to describe dynamic capability systems via various methods involving passing capabilities down as reified objects of some sort.

      This of course also depends on some related static guarantees that a function can't access ambient capabilities not passed directly in their arguments, but this is a much simpler static guarantee than effect typing and doesn't require specific analysis over normal parameter types.

    • ajb a day ago

      Capabilities are more general than that. They have been around for a long time; one academic design implemented them in hardware in 1970[1]. they can be used in as fine grained a way as 'you are allowed to access this array in memory and nothing else'- which is the sort of thing that needs to be built into languages to be maximally useful.

      [1] https://en.wikipedia.org/wiki/CAP_computer

      • convolvatron a day ago

        I disagree about your last point. I looked at a product design once which allowed one to associate a profile with each third party library. accesses across library boundaries were implementing using classic call gates from segmented architectures which could change memory visibility and syscall filtering.

        so while I agree that language integration is really useful, I think you can get a lot out of appropriate support in the runtime, most notably the library loader.

        • ajb 7 hours ago

          Yes, that's why I said "to be maximally useful" instead of "to be useful"

zokier a day ago

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.

  • yencabulator 7 hours ago

    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).

  • mike_hearn a day ago

    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.

    • grncdr 19 hours ago

      > 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!

cudgy 16 hours ago

“All this has led me, slowly and reluctantly, to the conclusion that our dependency-heavy approach to building software is fundamentally incompatible with security.”

This vulnerability seemed so apparent though. I used to object in the past about all the dependencies We were adding that we had no idea how they were implemented, who implemented them, or why they were implemented. I always got pushback that I was holding back the team for moving quickly and using the latest frameworks. it is important to consider that many of these security issues derived from the methods that new developers are taught, which is strap together a bunch of libraries that you only use 5 to 10% of resulting in a massive application with tons of unknown threats and poor performance by the way. I mostly blame the largest tech companies like Google, Meta the turn out large frameworks that are overkill for 90% of the development out there. New developers held these companies in extremely high regard and considered their technology to be state of the art in all sense. Yes, they were state-of-the-art for solving the problems and Google and Meta needed, but adoption of these technologies by small startups and other companies has now made the dependency explosion project endemic.

The worst violators of this principle that I’ve noticed is the proliferation of web development, frameworks, like rails, react, etc. further, it is ironic that these platforms, the web platform in particular is promoted as more secure relative to the old active X model of running binaries directly in the browser. However, I would rather run a trusted binary with 5k lines of code in a browser or app that my team has fully vetted than 1200 libraries and millions of lines of code to accomplish the same task.

Perhaps this is a good use for AI that would scan source code for library dependencies for security threats or potential security threats. Another solution would be to break out libraries into smaller components that perform specific functional tasks. These would be easier to validate and also result in smaller applications. Obviously there is no easy solution and running binary in your browser is not a great solution either. However, we as developers need to consider the trade-off between danger say running a compact native app versus “safety“ of using jack of all trade frameworks that include millions of lines of code.

yencabulator 7 hours ago

> Addressing the first of these points requires at least somewhat rethinking of hardware and operating systems

The (vaporware) Mill CPU design has "portals" that are like fat function calls with byte-granularity MMU capability protection to limit mutual exposure between untrusting bits of of code on opposite sides of the portal. Think of it as cheap function-call-like syscalls into your kernel, but also usable for microkernel boundaries and pure userspace components.

https://www.youtube.com/watch?v=5osiYZV8n3U

Of course, we can't have nice things and are stuck with x86/arm/riscv, where it seems nothing better than CHERI is realistic and such security boundaries will suffer relatively-enormous TLB switching overheads.

nightpool a day ago

This is an interesting article to have up alongside the SLAP and FLOP vulnerabilities. I like capabilities as much as the next programmer, but my gut tells me that process boundaries are only going to get more important, not less, as chips get faster and untrusted code gets more widely understood. Or other sorts of hardward-enforceable memory boundaries

  • yencabulator 6 hours ago

    Yeah, it really seems capabilities and WASM sandboxes can't protect against speculation attacks. They'll both be very useful limiting what kinds of attacks can happen, still, since more isolation is either hard-to-program or slow on current hardware.

    Longer term, I think our hopes have to be at either cheaper MMU transitions between processes or in huge numbers of cheap cores.

    And for both of those, we'll need fast message passing. Either good frameworks for shared memory based message passing using today's tech, ones that guide people away from TOCTOU attacks; OR, hardware support for message passing, for example some sort of MMU ownership transfer / write-once memory sealing / read-once-into-local-memory / pass-ownership-of-cacheline or such that makes it easier to implement securely. Or for the lots of cheap cores scenario, some kind of hardware messaging primitive between cores.

    They say systems research is dead, I think it's just lacking funding, because all of the above sounds very much like a revival of stuff that was being researched earlier, with Barrelfish etc. The real challenge is changing the mainstream hardware. I find it hard to believe AMD isn't devoting a 5-person team for this sort of stuff, with the hope of discovering a "small feature" that could change the world of software. Or one of the RISC-V shops, though they have enough challenges already ahead of them.

Sytten a day ago

Side note, I think the serde yaml debacle was so predictable. As much as I admire Dtolnay his choice to archive the repository and push a deprecated version on cargo made everybody scramble for an alternative "maintained" crate is on him. You can say whatever you want about checkbox security but most people still have to deal with it if only to make the tooling shut up so they can do their work.

Maybe the rust fondation should take over more of those fundamental crates when maintainers are not willing or able to continue working on them. A similar problem happened with the zip crate which was transferred rather fast to a new maintainer and most people still use a very old version pre-transfer.

binary132 14 hours ago

I do not foresee the status quo improving on this front. If anything, it will continue to get worse until we are forced to deal with a massive problem that will make the security crises we’ve dealt with up til now look like a walk in the park.

ozim a day ago

There are already SBOM software bill of materials standards CycloneDX and SPDX in development and in use. There is VEX and also SLSA.

Idea is if everyone does legwork to check his dependencies you can trust your dependencies because they checked theirs.

It is still trust but we go implicit into „hey you sure you checked dependencies and for sure you did not just npm install library some kid from Alaska created who pulled his dependency on kid from Montenegro?”.

Including random libraries just because we can and it had enough stars on GH was bad idea already - but nowadays it becomes an offense and rightly so.

newpavlov a day ago

I think there is only one proper solution to the security problem of transitive dependencies: an open database of vetted/rejected libraries and tooling which would help to pull dependency versions according to configured rules.

For example, by trusting several big players such as Rust Foundation, Servo, Mozilla, Google, Facebook, etc. (developers will decide for themselves whom exactly they trust) who would manually review dependencies used by them we will be able to cover the most important parts of the ecosystem and developers will be able to review more minor dependencies in their projects themselves. cargo-crev + cargo-audit come somewhat close to what is needed, everything else is a matter of adoption.

Capabilities and other automated tools can help immensely with manual reviews, but can not replace them completely, especially in compiled languages like Rust.

>It’s easy for me to forget that the trust I place in those 20 direct dependencies is extended unchanged to the 161 indirect dependencies.

Unfortunately, when people mention such numbers they commonly do not account for the difference between "number of libraries in the dependency tree" and "number of groups responsible for the dependency tree". In practice, the latter number is often significantly smaller than the former. In other words, many projects (at least in the Rust world) lean towards the "micro-crate" approach, meaning that one group may be responsible for 20 crate in the dependency tree, which does not make security risks 20x bigger.

  • neipat a day ago

    I'm building a company in this area that looks like something similar. The goal is to provide a safer source for open source application dependencies that augments/replaces e.g. NPM.

    We take open source dependencies and:

    - Patch vulnerabilities, including in transitive dependencies, even for old or EoL versions that teams may be on

    - Continuously vet new versions that are published for malware; and don't bring them into the registry if so

    - Inline dependencies that don't need to be separate packages (e.g. fold in trim-newlines, a 1-line NPM package, into a parent package) to simplify dependency trees

    This is then available to developers as a one line change to switch to in e.g. package.json. Once you switch, you no longer need to manually review packages or do any of this scanning/upgrading/vulnerability management work, since you can trust and set policies on the registry.

    We're in the very early days and working with a few future-minded developers to get feedback on the design. If you're interested, I'd love to share more! Please email me at neil@syntra.io

    • newpavlov a day ago

      Sounds interesting! But I work with Rust, so your project is outside of my direct area of interest.

      If I am to suggest something, I think you should consider opening some parts of your product, e.g. you could publish your package reviews with an N-months delay and accept public reviews from the community with some vetting process on top.

      • neipat a day ago

        That's a great point. We've been thinking through how we work with open source maintainers and the community to crowdsource reviews or usage information.

  • Ygg2 a day ago

    What is "numbers of groups responsible" in context of Cargo? Github orgs?

    • newpavlov a day ago

      Roughly, yes. But it may be just one developer such as burntsushi.

      For example, by adding the aes-gcm crate to your dependencies you pull whooping 19 dependencies in total, but 13 of those are part of the RustCrypto org and remaining 5 are fairly "foundational" (libc, getrandom, cfg-if, typenum, subtle), meaning that security implications of such "big" dependency tree are not as bad as they seem at first glance.

JoachimSchipper a day ago

I really like this article. I do think it's useful to consider that the unit of isolation ("process") of the cloud era is a VM or container, and that the major clouds do have some sort of permissions model.

grinkelhoof a day ago

I'm going to take a wild guess that WASM is orders of magnitude slower for IPC than raw unix, which is unfortunate because it seems like some of the most promising fertile soil for a security-first capability model.

Does that disqualify it as a potential path to a solution? How fine-grained would these components realistically need to be?

Ygg2 a day ago

My one big problem with the title and the way this blog about is that it assumes infinite scaling - in performance, correctness, size, security. What works on a small scale is ludicrous to work on a huge one.

There is an assumption that your blog and your multi-billion SAAS should have transferrable skills. It's like expecting a person designing a shack and the person designing the next Fort Knox to use the same plans, materials, and people. Either you get extremely overbuilt shacks, with vault doors, separate HVAC and OSHA regulations that take decades to build and will cost you several billion dollars, or Fort Knox that anyone can kick down vault doors and steal money.

If your blog, or your 72h hackathon game takes 3000 dependencies, and maybe one of them is malicious (which is low probability) who cares?

If your multi-million SaaS has 3000 dependencies, yeah, it's time to slim it down. Granted, no one wants to do this because it costs money, and takes time away from shipping another feature.