rust-secure-code / cargo-sandbox

Perform Cargo builds inside of a sandboxed environment
Apache License 2.0
52 stars 1 forks source link

Determine project goals #3

Open tarcieri opened 5 years ago

tarcieri commented 5 years ago

At a high-level, the goal of this project is to perform cargo builds inside of a sandboxed environment which restricts, to some extent, the capabilities of any code that executes at build-time.

A rationale for why this is valuable can be found in my Rust 2019 blog post: Security, Maturity, Stability

tl;dr: build-time attacks are stealthier than trojans in build targets, and permit lateral movement between projects when attacking a build system. The threat of a build-time trojan, versus a source code trojan, is an attack that does not leave behind forensic evidence and is therefore harder to investigate. Attacking a build system also potentially permits lateral movement between build targets.

That said, both the threat model and high-level design of this tool are debatable, and this issue is a place to discuss these matters.

Additional background:

tarcieri commented 5 years ago

I've opened an initial PR (#4) to propose gaol as the sandboxing mechanism.

sanxiyn commented 5 years ago

I am not sure where to post this, so I will just post it here. I think OpenBSD pledge is a well-designed approach.

Siosm commented 5 years ago

This is an initial example that will restrict cargo write access to its crate cache, the registry and the target directory using bubblewrap on Linux:

bwrap \
    --unshare-ipc --unshare-pid --unshare-uts --unshare-cgroup \
    --ro-bind / / --dev /dev --tmpfs /tmp \
    --bind $PWD/target $PWD/target \
    --bind $HOME/.cargo/git $HOME/.cargo/git \
    --bind $HOME/.cargo/registry $HOME/.cargo/registry \
    -- cargo build

This may be improved depending on the objectives: for example, this does not constrain network access at all.

tarcieri commented 5 years ago

@Siosm neat! That seems worth considering

Siosm commented 5 years ago

Here is an improved version that will (on top of previous example functionality):

#!/usr/bin/bash

set -eu

main() {
    local pwd="${PWD}"
    local home="/home/tim"
    local project="${home}/$(basename ${pwd})"

    env -i bwrap \
        --unshare-ipc \
        --unshare-pid \
        --unshare-uts \
        --unshare-cgroup \
        --new-session \
        --ro-bind / / \
        --tmpfs /home \
        --tmpfs /tmp \
        --tmpfs /sys \
        --tmpfs /opt \
        --dev /dev \
        --dir /home/cargo \
        --ro-bind "${HOME}"/.cargo "${home}"/.cargo \
        --bind "${HOME}"/.cargo/git "${home}"/.cargo/git \
        --bind "${HOME}"/.cargo/registry "${home}"/.cargo/registry \
        --ro-bind "${HOME}"/.rustup "${home}"/.rustup \
        --ro-bind "${pwd}" "${project}" \
        --bind "${pwd}"/target "${project}"/target \
        --chdir "${project}" \
        --setenv PATH "/bin:/sbin:/usr/bin:/usr/sbin:${home}/.cargo/bin" \
        -- cargo "${@}"
}

main "${@}"

One may use PATH tricks to make it the default command run when calling cargo.