| ▲ | homebrewer 5 days ago |
| I also use bubblewrap to isolate npm/pnpm/yarn (and everything started by them) from the rest of the system. Let's say all your source code resides in ~/code; put this somewhere in the beginning of your $PATH and name it `npm`; create symlinks/hardlinks to it for other package managers: #!/usr/bin/bash
bin=$(basename "$0")
exec bwrap \
--bind ~/.cache/nodejs ~/.cache \
--bind ~/code ~/code \
--dev /dev \
--die-with-parent \
--disable-userns \
--new-session \
--proc /proc \
--ro-bind /etc/ca-certificates /etc/ca-certificates \
--ro-bind /etc/resolv.conf /etc/resolv.conf \
--ro-bind /etc/ssl /etc/ssl \
--ro-bind /usr /usr \
--setenv PATH /usr/bin \
--share-net \
--symlink /tmp /var/tmp \
--symlink /usr/bin /bin \
--symlink /usr/bin /sbin \
--symlink /usr/lib /lib \
--symlink /usr/lib /lib64 \
--tmpfs /tmp \
--unshare-all \
--unshare-user \
"/usr/bin/$bin" "$@"
The package manager started through this script won't have access to anything but ~/code + read-only access to system libraries: bash-5.3$ ls -a ~
. .. .cache code
bubblewrap is quite well tested and reliable, it's used by Steam and (IIRC) flatpak. |
|
| ▲ | aorth 14 hours ago | parent | next [-] |
| Very cool idea. Thanks for sharing. I made some minor tweaks based on feedback to your comment: #!/usr/bin/env bash
#
# See: https://news.ycombinator.com/item?id=45034496
bin=$(basename "$0")
echo "==========================="
echo "Wrapping $bin in bubblewrap"
echo "==========================="
exec bwrap \
--bind ~/.cache ~/.cache \
--bind "${PWD}" "${PWD}" \
--dev /dev \
--die-with-parent \
--disable-userns \
--new-session \
--proc /proc \
--ro-bind /etc/ca-certificates /etc/ca-certificates \
--ro-bind /etc/resolv.conf /etc/resolv.conf \
--ro-bind /etc/ssl /etc/ssl \
--ro-bind /usr /usr \
--setenv PATH /usr/bin \
--symlink /usr/bin /bin \
--symlink /usr/bin /sbin \
--symlink /usr/lib /lib \
--symlink /usr/lib64 /lib64 \
--tmpfs /tmp \
--unshare-all \
--unshare-user \
--share-net \
/usr/bin/env "$bin" "$@"
Notably `--share-net` should be moved down since it is negated by `--unshare-all`. I also added a reminder that the command is being bubblewrapped, modified the second read-write bind to the current directory, and changed the final exec to use `/usr/bin/env` to find the binary so it can be more flexible. I tested it with npm and yarn just now and it seems to work well. Thanks! |
|
| ▲ | internet_points 5 days ago | parent | prev | next [-] |
| Thanks, handy wrapper :) Note: --symlink /usr/lib /lib64 \
should probably be `/usr/lib64`and --share-net \
should go after the `--unshare-all --unshare-user`Also, my system doesn't have a symlink from /tmp to /var/tmp, so I'm guessing that's not needed for me (while /bin etc. are symlinks) |
|
| ▲ | TheTaytay 5 days ago | parent | prev | next [-] |
| Very cool. Hadn't heard of this before. I appreciate you posting it. |
|
| ▲ | oulipo2 5 days ago | parent | prev | next [-] |
| Will this work on osX? and for pnpm? |
| |
| ▲ | aragilar 5 days ago | parent [-] | | No, bubblewrap uses linux namespaces. You can use for (almost) whatever software you want. |
|
|
| ▲ | johnisgood 5 days ago | parent | prev | next [-] |
| Firejail is quite good, too. I have been using firejail more than bubblewrap. |
|
| ▲ | shermantanktop 5 days ago | parent | prev | next [-] |
| This is trading one distribution problem (npx) for another (bubblewrap). I think it’s a reasonable trade, but there’s no free lunch. |
| |
| ▲ | homebrewer 5 days ago | parent [-] | | Not sure what this means. bubblewrap is as free as it gets, it's just a thin wrapper around the same kernel mechanisms used for containers, except that it uses your existing filesystems instead of creating a separate "chroot" from an OCI image (or something like it). The only thing it does is hiding most of your system from the stuff that runs under it, whitelisting specific paths, and optionally making them readonly. It can be used to run npx, or anything else really — just shove move symblinks into the beginning of your $PATH, each referencing the script above. Run any of them and it's automatically restricted from accessing e.g. your ~/.ssh https://wiki.archlinux.org/title/Bubblewrap | | |
| ▲ | conception 5 days ago | parent [-] | | It means that someone just has to compromise bubblewrap instead of the other vectors. | | |
| ▲ | johnisgood 5 days ago | parent | next [-] | | This is such a defeatist perspective. You could say this about anything ad nauseum. I think bubblewrap (or firejail) is less likely to be a successful target. | |
| ▲ | haswell 5 days ago | parent | prev | next [-] | | While this may be true, this is still a major improvement, no? i.e. it seems far more likely that a rapidly evolving hot new project will be targeted vs. something more stable and explicitly security focused like bubblewrap. | |
| ▲ | throwawaysoxjje 5 days ago | parent | prev | next [-] | | Am I getting bubblewrap somewhere other than my distro? What makes it different from any other executable that comes from there? | | |
| ▲ | shermantanktop 4 days ago | parent [-] | | Nothing. Does your threat model assume 100% trust in your distro? I understand saying you trust it a lot more than the garbage on npm. But if your trust is anything less than 100%, you are balancing risk and benefit. |
| |
| ▲ | cozzyd 5 days ago | parent | prev | next [-] | | sure but surely one gets bubblewrap from their distro, and you have to trust your distro anyway. | |
| ▲ | theamk 5 days ago | parent | prev [-] | | Not "instead", it's "in addition to". Your classical defense-in-depth. | | |
| ▲ | oulipo2 5 days ago | parent [-] | | No, "instead". If they compromise bubblewrap to send out your files, and you run bubblewrap anyway for any reason, you're still compromised. But obviously you can probably safely pin bubblewrap to a given version, and you don't need to "install packages through it", which is the main weakness of package managers | | |
| ▲ | ChocolateGod 5 days ago | parent | next [-] | | Bubblewrap uses the same Linux functions that billion dollar cloud infrastructure use. Bubblewrap does no sandboxing/restrictions itself, it's instructing the kernel to do it. | |
| ▲ | aragilar 5 days ago | parent | prev [-] | | How? bubblewrap isn't something someone has randomly uploaded to npm, it has well known maintainers and a well organised release process (including package signing). Which is easier to do: upload a package to npm and get people to use it, or spend 2+ years trying to become a maintainer of bubblewrap or one of its dependencies to compromise it. | | |
| ▲ | oulipo2 5 days ago | parent [-] | | Sure, but there's plenty of packages with well-known maintainers who get compromised... | | |
| ▲ | haswell 5 days ago | parent [-] | | The fact that something can happen is separate from how likely that thing is to happen, and that’s what matters here. The comments here that point to this theoretical possibility seem to be missing the point, which is that using something like bubblewrap is an improvement over running arbitrary projects un-sandboxed, and the likelihood of such an attack is far less than the likelihood of any one of hundreds of rapidly evolving, lesser known, lesser scrutinized projects getting compromised. |
|
|
|
|
|
|
|
|
| ▲ | 4 days ago | parent | prev [-] |
| [deleted] |