Something went wrong. Try again.
atproto git client
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107#!/usr/bin/env bash# Run the test suite where it cannot reach the real home directory, and fail# if anything tried to.## Two different problems, both handled here because neither is enough alone:## containment a sandbox stops a test writing to ~/.config/atgc# detection an assertion says that a test tried## A sandbox on its own is silent. The escape still happens, into a home that# is thrown away, and nobody learns anything -- which is how four unit tests# came to be depositing a `did:plc:alice` directory in a real configuration# directory while the suite stayed green. So each binary gets a fresh home# that is inspected afterwards, and the run is refused if one is not empty.## The binaries are built outside the sandbox and only *run* inside it, so# nothing here needs a toolchain, a network, or an image.set -uo pipefail
cd "$(dirname "$0")/.."repo=$PWDhomes=$repo/target/test-homesrm -rf "$homes"; mkdir -p "$homes"
echo "building test binaries..."# Only artifacts cargo marks as tests. The same stream carries the `atgc`# binary itself, and running the CLI with a test runner's flags is not a test# failing -- it is a command refusing an argument it has never heard of.mapfile -t bins < <(cargo test --no-run --message-format=json 2>/dev/null | python3 -c 'import json, sysfor line in sys.stdin: try: m = json.loads(line) except ValueError: continue if m.get("reason") == "compiler-artifact" and m.get("executable") \ and m.get("profile", {}).get("test"): print(m["executable"])' | sort -u)if [ ${#bins[@]} -eq 0 ]; then echo "no test binaries were built" >&2 exit 1fi
# `--dev-bind / /` then a tmpfs over the home: everything the toolchain needs# stays visible, and the one directory the suite must not touch is replaced by# an empty one. The cargo and rustup trees are bound back read-only because a# test binary may still resolve a linker or a runtime out of them.# Bubblewrap is the containment half and it is optional: without it the run# still gets a fresh home per binary and still refuses an escape, which is the# half that finds bugs. A CI image that lacks it -- or forbids user namespaces# -- gets the detection anyway rather than a skipped check.# ATGC_NO_BWRAP=1 takes the fallback on a machine that has bubblewrap, which# is the only way to exercise that path before CI does.have_bwrap=0if [ -z "${ATGC_NO_BWRAP:-}" ] && bwrap --dev-bind / / true >/dev/null 2>&1; then have_bwrap=1fi[ $have_bwrap -eq 1 ] || echo "note: bubblewrap unavailable; isolating by HOME alone"
sandbox() { local home=$1; shift if [ $have_bwrap -eq 0 ]; then env HOME="$home" XDG_CONFIG_HOME="$home/.config" "$@" return fi bwrap --dev-bind / / \ --tmpfs "$HOME" \ --tmpfs /tmp \ --bind "$repo" "$repo" \ --bind "$home" "$home" \ ${CARGO_HOME:+--ro-bind "$CARGO_HOME" "$CARGO_HOME"} \ --ro-bind-try "$HOME/.cargo" "$HOME/.cargo" \ --ro-bind-try "$HOME/.rustup" "$HOME/.rustup" \ --setenv HOME "$home" \ --setenv XDG_CONFIG_HOME "$home/.config" \ --die-with-parent \ "$@"}
failed=0for bin in "${bins[@]}"; do name=$(basename "$bin") home=$homes/$name mkdir -p "$home"
if ! sandbox "$home" "$bin" --quiet; then echo "FAIL $name" failed=1 fi
# The home is inspected from outside, after the sandbox is gone. Anything # here is a test that reached for the real configuration directory and # would have found it on a developer's machine. if [ -n "$(ls -A "$home" 2>/dev/null)" ]; then echo "ESCAPED $name wrote outside its temporary directories:" find "$home" | sed 's|^| |' failed=1 fidone
if [ $failed -eq 0 ]; then echo "all ${#bins[@]} test binaries passed, and none touched the home directory"fiexit $failed