A single bash script that runs a coding harness (pi by default) inside a rootless Ubuntu 24.04 container with only the current directory mounted at /project, an explicit egress allowlist and an explicit environment: nothing is passed in that was not named on the command line or in a config file. Network enforcement here is empirical rather than assumed (tests/spike_network.sh, docs/networking.md). The original design -- a sidecar proxy on an internal network -- does not work rootless on this host, so allow mode runs pasta with --map-host-loopback, installs an inet aisb ruleset inside the container that drops every egress path except the gate's, and relays through a squid gate bound to the host's loopback that resolves names itself and refuses anything unlisted. The entrypoint checks that the default-drop rule really exists before setpriv drops to uid 1000 with an empty capability set, and exits 77/78 rather than run unenforced. The Containerfile, the entrypoint, the squid config generator and the ruleset renderer all live in bin/ai-sandbox, and the image is tagged by content hash, so a policy change can never silently reuse a stale image. Tests are pure bash: 161 assertions start no container and touch no network, 256 run real ones, including proof that a raw socket, a stripped proxy env and DNS all stay blocked while an allowlisted host works over both http and CONNECT. LLM-Generated: true
66 lines
2.7 KiB
Bash
Executable File
66 lines
2.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# tests/unit/04_env.sh -- environment passing and secret hygiene.
|
|
source "$TESTS/lib.sh"
|
|
|
|
PROJ="$WORK/proj"; mkdir -p "$PROJ"; cd "$PROJ" || exit 1
|
|
export AISB_CONFIG_DIR="$WORK/cfg-empty"; mkdir -p "$AISB_CONFIG_DIR"
|
|
export AISB_CANARY=hunter2-secret-value
|
|
export AISB_EMPTY_VAR=""
|
|
unset AISB_NOT_SET
|
|
|
|
t_name "deny by default"
|
|
sb --print-policy --net none
|
|
assert_eq "env_names=" "$(printf '%s' "$OUT" | grep '^env_names=')" "nothing is passed by default"
|
|
assert_absent "CANARY" "a host variable is not passed unless asked for"
|
|
|
|
t_name "explicit passing"
|
|
sb --print-policy --net none --env AISB_CANARY
|
|
assert_contains "env_names=AISB_CANARY" "named variable is queued"
|
|
assert_absent "hunter2" "the value never appears in --print-policy output"
|
|
sb --dry-run --net none --env AISB_CANARY
|
|
assert_absent "hunter2" "the value never appears in the printed podman invocation"
|
|
assert_contains "<env-file:0600>" "values travel through a 0600 env file, not the command line"
|
|
|
|
t_name "set-but-empty passes, unset fails closed"
|
|
sb --print-policy --net none --env AISB_EMPTY_VAR
|
|
assert_contains "env_names=AISB_EMPTY_VAR" "empty value still passes"
|
|
assert_absent "env_missing=AISB_EMPTY_VAR" "empty value is not 'missing'"
|
|
sb --print-policy --net none --env AISB_NOT_SET
|
|
assert_rc 0 "--print-policy warns instead of dying"
|
|
assert_contains "not set in the host environment" "the warning names the problem"
|
|
assert_contains "env_missing=AISB_NOT_SET" "env_missing reports it"
|
|
|
|
t_name "literal values"
|
|
sb --dry-run --net none --env FOO=bar
|
|
assert_contains "<env-file:0600>" "literal values also go through the env file"
|
|
assert_absent "bar" "literal values are not echoed into the invocation"
|
|
|
|
t_name "env files"
|
|
cat > "$WORK/envfile" <<'EOF'
|
|
# comment
|
|
AISENV_ONE=1
|
|
AISENV_TWO=with spaces
|
|
AISENV_THREE=has=equals
|
|
EOF
|
|
chmod 600 "$WORK/envfile"
|
|
sb --print-policy --net none --env-file "$WORK/envfile"
|
|
assert_contains "env_names=AISENV_ONE AISENV_TWO AISENV_THREE" "all three names queued"
|
|
sb_env AISENV_ONE=1 --print-policy --net none --env AISB_CANARY --env-file "$WORK/envfile"
|
|
assert_contains "AISENV_THREE" "env file entries pass"
|
|
assert_contains "AISB_CANARY" "and combine with --env"
|
|
|
|
t_name "loose env-file permissions warn"
|
|
chmod 644 "$WORK/envfile"
|
|
sb --print-policy --net none --env-file "$WORK/envfile"
|
|
assert_contains "chmod 600 recommended" "world-readable env file warns"
|
|
chmod 600 "$WORK/envfile"
|
|
|
|
t_name "invalid names and values"
|
|
sb --print-policy --net none --env 9BAD
|
|
assert_rc 1 "invalid variable name rejected"
|
|
sb --print-policy --net none --env-file "$WORK/does-not-exist"
|
|
assert_rc 1 "missing env file rejected"
|
|
export AISB_MULTILINE=$'one\ntwo'
|
|
sb --print-policy --net none --env AISB_MULTILINE
|
|
assert_rc 1 "multi-line values are rejected rather than silently truncated"
|