A useful tool I created a few years ago but never really promoted much: usand

https://github.com/richfelker/usand

It creates no-network (cutting off main exfil vectors), read-only except for current dir and descendants, sandboxed environment to run low-trust code, even full build processes, within.

Only dependency is unshare(1) utility and Linux kernel with unprivileged namespace functionality.

GitHub - richfelker/usand: usand - convenient and minimal unshare(1)-based sandbox

usand - convenient and minimal unshare(1)-based sandbox - richfelker/usand

GitHub
Nowadays I pretty much always run make under usand.sh, just so I know it's not unexpectedly fetching stuff from the internet or messing with global state in my homedir.

It's probably not a hard enough boundary for defending against *adversarial* code prepared to be running under it, so I wouldn't really recommend it for that, but it's great for low-trust or casually-hostile stuff.

I'd love bug reports with PoCs showing weaknesses of it that could be improved upon.

I also have, unpublished, a reverse direction tool called ownroot.sh - and it's even stackable with usand.sh.

ownroot.sh (sadly) doesn't pwn root, but makes it so you're the owner of your own /, via bind mounts and pivot_root, and comes with a forkdir.sh utility that lets you do the same with additional dirs.

This means you can install ld-musl-$ARCH.so.1 in /lib or edit resolv.conf or hosts in /etc, just for one session, all as user.

@dalias So you'd have something like plan9's namespace then, or am i not understanding
@piusbird I think it's weaker than plan9, but not sure. Linux gives some fairly powerful tools to build this kind of namespacing/sandboxing, but they're klunky to use and designed around being (near) zero-cost rather than being good abstractions or giving control at the best levels to make good policies.

@dalias @piusbird yeah union mounts in Linux, in particular, are very clunky compared to in plan 9, though most Linux users would find the way they work in plan 9 kinda strange (duplicate filenames are a thing).

And user mode filesystem servers (through fuse) are a lot more complicated as well, where on plan 9 they're super easy to make and use.

Linux equivalents to plan 9 stuff always feel very much like a fun mirror version.

@megmac @piusbird The version I would like is fully user-nestable, where, when you sandbox a [tree of] process[es], all the fs access requests come thru to a fs-providing process you provide, that interprets them and can then give back a handle to an fs object from its provider (all the way back to original kernel) or a handle to some object it provides.

And likewise for other resources like network, user ids, shared memory objects, anon memory, etc.

Someday maybe...

@dalias @piusbird that's definitely a kind of thing you can do with plan 9. It's more or less how running things on a remote host works.

Sadly, the future was 30 years ago. Not that there aren't any modern OS' that can do that (I work on one), but none are as useful as Linux.

@dalias "if you can read this bug report you've been pwned"

@dalias I really think that more build systems should just work like this by default.

There's really way too much code we're running blindly with full privilege as our user, and way too many ways that can go wrong either accidentally or maliciously.

@unlambda My ideal make has this enforced at the declarative rule level: rules can't write anything but temp files or declared outputs, can't read any part of the project tree but declared dependencies.
@dalias Yeah. That would be a bit harder to implement in practice, actually declaring all dependencies (including things like system libraries), is going to be harder to move existing builds to, but you're right, that really is the way it should work.
@unlambda I would start by making system level stuff always visible, only in-project file deps hidden unless declared. This would theoretically work with existing well written makefiles.
@dalias @unlambda i think a package manager and build system are probably different things and a package manager can expose hooks to link against system libs while a build system can actually perform the linking. right now the package manager and build tool i am trying to do this with is spack and pants but for any new project i would encourage you to consider this package manager / build system distinction and potentially make those use cases into separate tools or at least interfaces
@dalias @unlambda have worked on one implementation of this previously in the pants build tool https://www.pantsbuild.org/2.18/docs/writing-plugins/the-rules-api/processes
Processes | Pantsbuild

How to safely run subprocesses in your plugin.

@unlambda @dalias this is really nice to see. Tools like Artifactory have features to do similar things (local package cache, etc.) but the discipline of "no network" also forces a more intentional approach to builds and dependencies, which itself is A Good Thing.

💖

@matthewskelton @unlambda No network is there because it's the only easy way to make it "fairly safe" to leave a read only view of the user account visible. I think to make it so only world readable files were still visible you'd need more elaborate machinery like FUSE or 9p proxying of the filesystem, or some kind of ptrace or seccomp based filter.
@dalias "casually hostile" is such a perfect description, and such a useful label right now.
@dalias very cool! I’ve made something similar, using docker: https://github.com/codecat/disco
GitHub - codecat/disco: Disposable development containers

Disposable development containers. Contribute to codecat/disco development by creating an account on GitHub.

GitHub
@codecat Yeah, the difference with usand is you just have all your configuration, environment, tools from the host automatically, but without anything you do being able to spill back on them.