I already posted a longer version of this post on r/rust, however, I thought it would be useful not only for Rust community, but for anyone who uses developers' build tools (cargo, npm, pip etc.), since the problem that cijail solves is common for all of them.
I wanted to make a tool to protect CI/CD pipelines from supply chain attacks (see https://wildwolf.name/secure-way-run-npm-ci/ and https://internals.rust-lang.org/t/about-supply-chain-attacks... for the examples of such attacks). My first attempt was too naive to have any practical use, and I was suggested (https://www.reddit.com/r/rust/comments/163ngog/comment/jy3yx...) to use Linux Seccomp as a more robust alternative.
After a while I wrote cijail tool that whitelists HTTPS URLs, Linux socket endpoints (ip + port, netlink, unix) and DNS names. The tool works inside Docker container and does not require any privileges (although in some cases you need to specify CAP_SYS_PTRACE which is immediately dropped before running the actual command). As far as I can tell it is really difficult to circumvent Seccomp, as it is kernel-level technology. However, I had to block a few namespace-related system calls as well as calls that allow one to write other process's memory to be on the safe side.
I tested the tool with cargo, npm and pip and wrote an article about my findings (https://staex.io/blog/cijail-how-to-protect-your-ci-cd-pipel...).
To be completely honest with you, I think protection from supply chain attacks is much easier to implement on the build tool level (cargo, npm, pip etc.) than writing another process jail. Similar maintainers' tools (Nix, Guix, RPM, DEB build systems) split the build into "download" and "build" phases. In the first phase the dependencies are downloaded, but the scripts are not executed. In the second phase the scripts are executed, but network access is prohibited. This removes possibility to exfiltrate any valuable data.
There are a few problems that I see in implementing such phases for cargo, npm and pip. These tools already have "download" and "build" commands in some form, but the network access is not prohibited by default during "build" phase. Adding "unshare -rn" will block network access, but in a Docker container unshare system call is blacklisted. Prohibiting network access might break some packages that download dependencies in their scripts.
Despite all of these problems implementing two build phases would completely remove the possibility of data exfiltration via side channels (e.g. DNS), and it has already been done this way in maintainers' tools.
So, what do you think: do developers' build tools (cargo, npm, pip etc.) need to prohibit network access during build phase by default to protect us from supply chain attacks?