On Tue, Jul 21, 2026 at 04:44:05AM +0000, Lawrence, Richard E wrote:
Hello David,
Thank you for your feedback. I see your point that I haven't made the case why this feature is worthwhile. I would like to explain how I came to my position.
Thanks!
I want to do bubblewrap + pasta so that I can give my personal agent sandboxed code execution to support SKILLS.md extensions. A very common pattern in SKILLS.md is python code with inline script metadata dependencies so that uvx can generate ephemeral virtual environments on demand to run the scripts. This strategy requires granting access to the internet, but I still want to deny access to ports on localhost. I don't want a confused agent or malicious third party scripts to have the opportunity to tinker with other services running on my machine or those of my office neighbors.
Sounds like a good plan.
Pasta seemed like the right tool for the job. It can distinguish between local area and wide area outbound traffic.
So, not really relevant to the topic at hand, but a small word of caution here. I'd say pasta definitely aims to be the right tool for this job, but I'm not sure it yet does everything you want. We do distinguish between localhost (127.0.0.1/8 and ::1) traffic and other outbound traffic. We _don't_ otherwise distinguish between network destinations, though, so it won't really protect your network neighbours. We do intend to add forwarding/filtering rules for outbound traffic, but it's not done yet.
I tried many, many combinations for getting bwrap and pasta to get along.
I assume that pasta should be running before the sandboxed command begins to run in the container, since almost the first thing that would happen is the package manager uv reaching out to the internet to gather the script's dependencies. If pasta joins the namespace created by bwrap, then I have to somehow delay the start of the script execution until pasta signals that it is ready. That is a very scary proposition to me; I am not sure how I would do it even in theory. So that makes me want to start pasta first and then start bubblewrap.
Ok, fair point. Delaying the start of the internal command can certainly be done, but it is pretty fiddly.
On the other hand, since bwrap can't yet join existing network namespaces, it turned out to be a really difficult problem. I tried wrapping bubblewrap in nsenter, but that exposed a really subtle issue with nested namespaces. I don't 100% understand it, but in short, inner namespaces tend to implicity drop capabilities if they aren't very precisely managed. So the result of my attempt was that some commands like ping would not work inside the inner namespace because the user in the inner namespace didn't get mapped to the range of users in the outer namespace who are allowed to execute ping.
Ah! I'm not certain, but the problem here might be not to do with nested namespaces per se, but because nsenter usually drops the capabilities it gets by entering the namespace. Or, more precisely, it doesn't by default allow the caps it has to pass on to the command it spawns. Try adding --keep-caps to the nsenter command line - at least if you have a new enough util-linux. I added that option myself ~3 years ago to deal with similar sounding problems (unshare has had a similar option for much longer, I just added the nsenter one).
I tried executing bubblewrap within pasta. And it's so close to being what I wanted! It's a simple one-liner and for some reason I don't understand, avoids the issue with the nested namespace. But it still isn't what I wanted, because another thing I like to do is deliver bwrap's many many args to it via a file descriptor (--args FD) to simplify the process name for ps and avoid leaking private information to anyone else running on the same node. But since pasta couldn't pass FD's through to bubblewrap, so now I have to wrap my bubblewrap command inside some other bespoke script whose job is to open a temporary file I am serving somewhere, which just becomes another opportunity to leak my private information.
Right. I certainly agree that passing the fds into your command is a good approach. The question is whether there's a practical way to do that without spawning the command directly from pasta.
Sidebar: if you think about it, the only reason the nsenter strategy can even be considered a "workaround" for pasta not having --pass-fd is that nsenter does have the feature to pass FD's through (in fact, it is the default). That's not a good look for pasta.
Well.. it's a question of the context for each program. nsenter is a system tool, it's not really it's job to restrict what you or it can do beyond what the kernel enforces. pasta, on the other hand is an end user tool that has to process traffic from an untrusted guest. For that reason, we try to have multiple layers of defense to limit the damage even if a malicious guest takes us over completely. That's why we close all open fds on entry, not because it's something that most programs would do.
Sidebar: Yes, it can be said that my problem would be solved on the bubblewrap side if only bubblewrap could join an existing network namespace. I also submitted the PR to create that feature. Nevertheless, I feel strongly that passing FD's has other plausible consumers besides specifically bubblewrap.
So, yes I think for the case of bubblewrap specifically it would make sense to do some integration there. But also, agreed, it's certainly not the only case where passing fds is useful.
In the end, I felt super, super frustrated because what seemed like an easy problem turned out to be nearly impossible. In my workplace, I am considered the local expert on containers, and even I couldn't figure it out. My LLM coding agent couldn't figure it out either. This would be completely hopeless for some gamer trying to isolate network access for a multiplayer game installed via flatpak.
That's understandable. It does seem like doing this with nsenter is rather trickier than I had thought. Would be nice to see if --keep-caps is the secret ingredient, though.
I teach the container shortcourse at my institution, and I genuinely care about the future of this technology. It is my hope to help make modern lightweight and secure container technologies as user-friendly as possible, so that more people will choose them over "sudo docker". If we can reach a consensus regarding the ideal scope of this feature, I will gladly address all your technical complaints.
Ok. You've more than halfway convinced me. Here's what I'd like to see: 1) Check if starting pasta first then running bwrap under nsenter --keep-caps can do the trick. Even if we do make the change to pasta, it would be nice to know if this workaround is usable for older versions. 2) Look into implementing this by delaying isolate_fds() until after the command is spawned. 3) If both of those fail, then I agree the case for --pass-fds is strong and I'll no longer object.
If you read this far, I am grateful for your attention, and I apologise for rambling. It is late here, and my brain don't work so good just before bed.
I know the feeling. -- David Gibson (he or they) | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you, not the other way | around. http://www.ozlabs.org/~dgibson