Comment by aorth
2 months ago
In the story about the Nx compromise a few weeks ago someone posted a neat script that uses bubblewrap on Linux to run tools like npm more safely by confining their filesystem access. https://news.ycombinator.com/item?id=45034496
I modified the script slightly based on some of the comments in the thread and my own usage patterns:
#!/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" "$@"
Put this in `~/.local/bin` and symlink it to `~/.local/bin/npm` and `~/.local/bin/yarn` (and make sure `~/.local/bin` is first in your `$PATH`). I've been using it to wrap npm and yarn successfully in a few projects. This will protect you against some attacks that use postinstall scripts to do nefarious things outside the project.
Is exactly why I composed bubblewrap-based sandbox-venv for Python: https://github.com/kernc/sandbox-venv
Dangerous times we live in.
> --bind "${PWD}" "${PWD}"
Pardon my ignorance, but couldn't a malicious actor just redefine $PWD before calling a npm script?
The above script wraps npm. PWD gets evaluated before npm is called (so PWD is expanded in the "outside" environment).
Of course, if your malicious actor has access to your environment already, they can redefine PWD, but that's assuming you're already compromised. This bwrap script is to avoid that malicious actor running malicious install scripts in the first place.
However, I don't think it protects you against stuff like `npm install compromised-executable && node_modules/.bin/execute-compromised-executable` – then you'd have to bwrap that second call as well. Or just bwrap bash to get a limited shell.
I was more thinking if the malicious script calls npm itself, recursively... it could even redefine $PATH again to skip the next call to the bubblewrap wrapper scriptlet. I don't know if bwrap protects from that.
1 reply →