Fix capabilities

This commit is contained in:
Samuel Aubertin
2026-03-09 21:34:06 +01:00
parent 87a23e9772
commit 1e97baa534
3 changed files with 781 additions and 71 deletions

View File

@@ -1,4 +1,4 @@
name=skz-sloptrap name=skz-sloptrap
packages_extra=bash make shellcheck jq podman packages_extra=bash make shellcheck jq podman iproute2 strace
capabilities=apt-install nested-podman packet-capture capabilities=apt-install nested-podman packet-capture
allow_host_network=false allow_host_network=false

538
sloptrap
View File

@@ -370,13 +370,23 @@ if [[ $# -eq 0 ]]; then
fi fi
if [[ $(id -u) -eq 0 ]]; then if [[ $(id -u) -eq 0 ]]; then
helper_dir=${SLOPTRAP_HELPER_DIR:-/run/sloptrap-helper} helper_dir=${SLOPTRAP_HELPER_DIR:-/tmp/sloptrap-helper}
mkdir -p "$helper_dir/queue" queue_dir="$helper_dir/queue"
chmod 700 "$helper_dir" mkdir -p "$queue_dir"
chmod 711 "$helper_dir"
chmod 700 "$queue_dir"
target_uid=${SLOPTRAP_HOST_UID:-}
target_gid=${SLOPTRAP_HOST_GID:-}
if [[ -n $target_uid && -n $target_gid ]]; then
chown "$target_uid:$target_gid" "$queue_dir"
fi
if [[ -n ${SLOPTRAP_ACTIVE_CAPABILITIES:-} ]]; then if [[ -n ${SLOPTRAP_ACTIVE_CAPABILITIES:-} ]]; then
/usr/local/bin/sloptrap-helperd & /usr/local/bin/sloptrap-helperd &
helper_pid=$! helper_pid=$!
fi fi
if [[ -n $target_uid && -n $target_gid ]]; then
exec setpriv --reuid "$target_uid" --regid "$target_gid" --clear-groups -- "$@"
fi
exec runuser -u sloptrap --preserve-environment -- "$@" exec runuser -u sloptrap --preserve-environment -- "$@"
fi fi
@@ -387,13 +397,25 @@ EOF
cat <<'EOF' cat <<'EOF'
#!/usr/bin/env bash #!/usr/bin/env bash
set -euo pipefail set -euo pipefail
umask 077
helper_dir=${SLOPTRAP_HELPER_DIR:-/run/sloptrap-helper} helper_dir=${SLOPTRAP_HELPER_DIR:-/tmp/sloptrap-helper}
queue_dir="$helper_dir/queue" queue_dir="$helper_dir/queue"
caps=${SLOPTRAP_ACTIVE_CAPABILITIES:-} caps=${SLOPTRAP_ACTIVE_CAPABILITIES:-}
audit_log=${SLOPTRAP_AUDIT_LOG:-/codex/state/capabilities.log} audit_log=${SLOPTRAP_AUDIT_LOG:-/codex/state/capabilities.log}
capture_root=${SLOPTRAP_CAPTURE_DIR:-/codex/state/captures}
workspace_root=${SLOPTRAP_WORKDIR:-/workspace}
pidfile="$helper_dir/helperd.pid"
mkdir -p "$queue_dir" "$(dirname "$audit_log")" mkdir -p "$queue_dir" "$(dirname "$audit_log")"
cleanup_pidfile() {
rm -f "$pidfile"
}
trap cleanup_pidfile EXIT INT TERM HUP
printf '%s\n' "$$" >"$pidfile"
chmod 644 "$pidfile" 2>/dev/null || true
has_capability() { has_capability() {
local needle=$1 local needle=$1
local token local token
@@ -412,6 +434,74 @@ log_action() {
printf '%s op=%s status=%s %s\n' "$(date -u +%FT%TZ)" "$op" "$status" "$details" >>"$audit_log" printf '%s op=%s status=%s %s\n' "$(date -u +%FT%TZ)" "$op" "$status" "$details" >>"$audit_log"
} }
resolve_path() {
local raw=$1
if command -v realpath >/dev/null 2>&1; then
realpath -m "$raw"
return
fi
case "$raw" in
/*) printf '%s\n' "$raw" ;;
*) printf '%s/%s\n' "$(pwd -P)" "$raw" ;;
esac
}
path_within_root() {
local root path
root=$(resolve_path "$1")
path=$(resolve_path "$2")
case "$path" in
"$root"|"${root}/"*)
return 0
;;
esac
return 1
}
claim_request_dir() {
local request_dir=$1
[[ -d $request_dir && ! -L $request_dir ]] || return 1
path_within_root "$queue_dir" "$request_dir" || return 1
chown root:root "$request_dir" 2>/dev/null || true
chmod 700 "$request_dir" 2>/dev/null || true
}
init_request_outputs() {
local request_dir=$1
local path
[[ ! -e "$request_dir/status" && ! -L "$request_dir/status" ]] || return 1
for path in "$request_dir/stdout" "$request_dir/stderr"; do
[[ ! -L $path ]] || return 1
rm -f "$path"
: >"$path"
chmod 600 "$path" 2>/dev/null || true
done
}
read_request_value() {
local path=$1
[[ -f $path && ! -L $path ]] || return 1
cat "$path"
}
validate_package_name() {
local package=$1
[[ $package =~ ^[A-Za-z0-9][A-Za-z0-9+.-]*$ ]]
}
validate_packet_interface() {
local iface=$1
[[ $iface =~ ^[A-Za-z0-9][A-Za-z0-9_.:@+-]*$ ]]
}
validate_capture_path() {
local path=$1
local resolved
resolved=$(resolve_path "$path")
path_within_root "$capture_root" "$resolved" && return 0
path_within_root "$workspace_root" "$resolved"
}
write_status() { write_status() {
local request_dir=$1 local request_dir=$1
local status=$2 local status=$2
@@ -427,7 +517,7 @@ run_apt_install() {
return return
} }
local packages_file="$request_dir/packages" local packages_file="$request_dir/packages"
if [[ ! -f $packages_file ]]; then if [[ ! -f $packages_file || -L $packages_file ]]; then
printf 'missing package list\n' >"$request_dir/stderr" printf 'missing package list\n' >"$request_dir/stderr"
write_status "$request_dir" 2 write_status "$request_dir" 2
log_action "apt-install" "packages=missing" 2 log_action "apt-install" "packages=missing" 2
@@ -440,6 +530,15 @@ run_apt_install() {
log_action "apt-install" "packages=empty" 2 log_action "apt-install" "packages=empty" 2
return return
fi fi
local package
for package in "${packages[@]}"; do
if ! validate_package_name "$package"; then
printf 'invalid package name %s\n' "$package" >"$request_dir/stderr"
write_status "$request_dir" 2
log_action "apt-install" "packages=invalid" 2
return
fi
done
if apt-get update >"$request_dir/stdout" 2>"$request_dir/stderr" \ if apt-get update >"$request_dir/stdout" 2>"$request_dir/stderr" \
&& apt-get install -y --no-install-recommends "${packages[@]}" >>"$request_dir/stdout" 2>>"$request_dir/stderr"; then && apt-get install -y --no-install-recommends "${packages[@]}" >>"$request_dir/stdout" 2>>"$request_dir/stderr"; then
write_status "$request_dir" 0 write_status "$request_dir" 0
@@ -466,25 +565,47 @@ run_packet_capture() {
return return
} }
local iface filter_file output_file stdout_mode local iface filter_file output_file stdout_mode
iface=$(<"$iface_file") iface=$(read_request_value "$iface_file" || true)
filter_file="$request_dir/filter" filter_file="$request_dir/filter"
output_file="$request_dir/output" output_file="$request_dir/output"
stdout_mode=0 stdout_mode=0
[[ -f "$request_dir/stdout_mode" ]] && stdout_mode=$(<"$request_dir/stdout_mode") [[ -f "$request_dir/stdout_mode" ]] && stdout_mode=$(read_request_value "$request_dir/stdout_mode" || true)
local -a cmd=(tcpdump -i "$iface") if ! validate_packet_interface "$iface"; then
if [[ -s $filter_file ]]; then printf 'invalid interface %s\n' "$iface" >"$request_dir/stderr"
local filter write_status "$request_dir" 2
filter=$(<"$filter_file") log_action "packet-capture" "interface=invalid" 2
local -a filter_tokens=() return
read -r -a filter_tokens <<< "$filter"
cmd+=("${filter_tokens[@]}")
fi fi
if [[ $stdout_mode != "0" && $stdout_mode != "1" ]]; then
printf 'invalid stdout mode %s\n' "$stdout_mode" >"$request_dir/stderr"
write_status "$request_dir" 2
log_action "packet-capture" "interface=$iface stdout=invalid" 2
return
fi
local -a cmd=(tcpdump -i "$iface")
if [[ -s $output_file ]]; then if [[ -s $output_file ]]; then
local capture_path local capture_path
capture_path=$(<"$output_file") capture_path=$(read_request_value "$output_file" || true)
if ! validate_capture_path "$capture_path"; then
printf 'output path must stay within %s or %s\n' "$capture_root" "$workspace_root" >"$request_dir/stderr"
write_status "$request_dir" 2
log_action "packet-capture" "interface=$iface output=invalid" 2
return
fi
mkdir -p "$(dirname "$capture_path")" mkdir -p "$(dirname "$capture_path")"
cmd+=(-w "$capture_path") cmd+=(-w "$capture_path")
fi fi
if [[ -s $filter_file ]]; then
local filter
filter=$(read_request_value "$filter_file" || true)
local -a filter_tokens=()
if [[ -n $filter ]]; then
read -r -a filter_tokens <<< "$filter"
fi
if [[ ${#filter_tokens[@]} -gt 0 ]]; then
cmd+=(-- "${filter_tokens[@]}")
fi
fi
if [[ $stdout_mode == "1" ]]; then if [[ $stdout_mode == "1" ]]; then
"${cmd[@]}" >"$request_dir/stdout" 2>"$request_dir/stderr" || { "${cmd[@]}" >"$request_dir/stdout" 2>"$request_dir/stderr" || {
write_status "$request_dir" 1 write_status "$request_dir" 1
@@ -506,6 +627,7 @@ while true; do
shopt -s nullglob shopt -s nullglob
request_dirs=("$queue_dir"/*.req) request_dirs=("$queue_dir"/*.req)
shopt -u nullglob shopt -u nullglob
pending_requests=0
if [[ ${#request_dirs[@]} -eq 0 ]]; then if [[ ${#request_dirs[@]} -eq 0 ]]; then
sleep 1 sleep 1
continue continue
@@ -513,9 +635,21 @@ while true; do
for request_dir in "${request_dirs[@]}"; do for request_dir in "${request_dirs[@]}"; do
[[ -d $request_dir ]] || continue [[ -d $request_dir ]] || continue
[[ ! -f "$request_dir/status" ]] || continue [[ ! -f "$request_dir/status" ]] || continue
op=$(<"$request_dir/op") pending_requests=1
: >"$request_dir/stdout" if ! claim_request_dir "$request_dir"; then
: >"$request_dir/stderr" log_action "request" "unsafe=1 path=$request_dir" 2
continue
fi
if ! init_request_outputs "$request_dir"; then
log_action "request" "unsafe-output=1 path=$request_dir" 2
continue
fi
if ! op=$(read_request_value "$request_dir/op"); then
printf 'missing operation\n' >"$request_dir/stderr"
write_status "$request_dir" 2
log_action "request" "op=missing" 2
continue
fi
case "$op" in case "$op" in
apt-install) apt-install)
run_apt_install "$request_dir" run_apt_install "$request_dir"
@@ -530,6 +664,9 @@ while true; do
;; ;;
esac esac
done done
if [[ $pending_requests -eq 0 ]]; then
sleep 1
fi
done done
EOF EOF
;; ;;
@@ -538,9 +675,68 @@ EOF
#!/usr/bin/env bash #!/usr/bin/env bash
set -euo pipefail set -euo pipefail
helper_dir=${SLOPTRAP_HELPER_DIR:-/run/sloptrap-helper} helper_dir=${SLOPTRAP_HELPER_DIR:-/tmp/sloptrap-helper}
queue_dir="$helper_dir/queue" queue_dir="$helper_dir/queue"
mkdir -p "$queue_dir" pidfile="$helper_dir/helperd.pid"
helper_running() {
local pid
[[ -r $pidfile ]] || return 1
pid=$(<"$pidfile")
[[ -n $pid ]] || return 1
kill -0 "$pid" 2>/dev/null
}
ensure_helper_ready() {
if [[ -w $queue_dir ]] && helper_running; then
return 0
fi
if [[ -z ${SLOPTRAP_ACTIVE_CAPABILITIES:-} ]]; then
printf 'slop-apt: capability helper is not available in this session\n' >&2
exit 1
fi
if ! command -v setpriv >/dev/null 2>&1; then
printf 'slop-apt: setpriv is required to bootstrap the capability helper\n' >&2
exit 1
fi
setpriv --reuid 0 --regid 0 --clear-groups -- env \
SLOPTRAP_HELPER_DIR="$helper_dir" \
SLOPTRAP_ACTIVE_CAPABILITIES="${SLOPTRAP_ACTIVE_CAPABILITIES:-}" \
SLOPTRAP_AUDIT_LOG="${SLOPTRAP_AUDIT_LOG:-/codex/state/capabilities.log}" \
SLOPTRAP_CAPTURE_DIR="${SLOPTRAP_CAPTURE_DIR:-/codex/state/captures}" \
SLOPTRAP_WORKDIR="${SLOPTRAP_WORKDIR:-/workspace}" \
SLOPTRAP_HOST_UID="${SLOPTRAP_HOST_UID:-$(id -u)}" \
SLOPTRAP_HOST_GID="${SLOPTRAP_HOST_GID:-$(id -g)}" \
bash -c '
set -euo pipefail
helper_dir=${SLOPTRAP_HELPER_DIR:-/tmp/sloptrap-helper}
queue_dir="$helper_dir/queue"
pidfile="$helper_dir/helperd.pid"
helper_bin=$(command -v sloptrap-helperd)
[[ -n $helper_bin ]] || exit 1
mkdir -p "$queue_dir"
chmod 711 "$helper_dir"
chmod 700 "$queue_dir"
chown "$SLOPTRAP_HOST_UID:$SLOPTRAP_HOST_GID" "$queue_dir"
if [[ -r $pidfile ]]; then
pid=$(<"$pidfile")
if [[ -n $pid ]] && kill -0 "$pid" 2>/dev/null; then
exit 0
fi
fi
"$helper_bin" >/dev/null 2>&1 &
for ((i=0; i<30; i+=1)); do
if [[ -r $pidfile ]]; then
pid=$(<"$pidfile")
if [[ -n $pid ]] && kill -0 "$pid" 2>/dev/null; then
exit 0
fi
fi
sleep 0.1
done
exit 1
'
}
if [[ ${1-} != "install" ]]; then if [[ ${1-} != "install" ]]; then
printf 'usage: slop-apt install <package...>\n' >&2 printf 'usage: slop-apt install <package...>\n' >&2
@@ -554,12 +750,14 @@ if [[ $# -eq 0 ]]; then
fi fi
for package in "$@"; do for package in "$@"; do
if [[ ! $package =~ ^[A-Za-z0-9+.-]+$ ]]; then if [[ ! $package =~ ^[A-Za-z0-9][A-Za-z0-9+.-]*$ ]]; then
printf 'slop-apt: invalid package name %s\n' "$package" >&2 printf 'slop-apt: invalid package name %s\n' "$package" >&2
exit 2 exit 2
fi fi
done done
ensure_helper_ready
request_dir=$(mktemp -d "$queue_dir/request.XXXXXX.req") request_dir=$(mktemp -d "$queue_dir/request.XXXXXX.req")
trap 'rm -rf "$request_dir"' EXIT INT TERM HUP trap 'rm -rf "$request_dir"' EXIT INT TERM HUP
printf 'apt-install\n' >"$request_dir/op" printf 'apt-install\n' >"$request_dir/op"
@@ -585,10 +783,97 @@ EOF
#!/usr/bin/env bash #!/usr/bin/env bash
set -euo pipefail set -euo pipefail
helper_dir=${SLOPTRAP_HELPER_DIR:-/run/sloptrap-helper} helper_dir=${SLOPTRAP_HELPER_DIR:-/tmp/sloptrap-helper}
queue_dir="$helper_dir/queue" queue_dir="$helper_dir/queue"
default_output=${SLOPTRAP_CAPTURE_DIR:-/codex/state/captures} default_output=${SLOPTRAP_CAPTURE_DIR:-/codex/state/captures}
mkdir -p "$queue_dir" "$default_output" workspace_root=${SLOPTRAP_WORKDIR:-/workspace}
pidfile="$helper_dir/helperd.pid"
mkdir -p "$default_output"
helper_running() {
local pid
[[ -r $pidfile ]] || return 1
pid=$(<"$pidfile")
[[ -n $pid ]] || return 1
kill -0 "$pid" 2>/dev/null
}
ensure_helper_ready() {
if [[ -w $queue_dir ]] && helper_running; then
return 0
fi
if [[ -z ${SLOPTRAP_ACTIVE_CAPABILITIES:-} ]]; then
printf 'slopcap: capability helper is not available in this session\n' >&2
exit 1
fi
if ! command -v setpriv >/dev/null 2>&1; then
printf 'slopcap: setpriv is required to bootstrap the capability helper\n' >&2
exit 1
fi
setpriv --reuid 0 --regid 0 --clear-groups -- env \
SLOPTRAP_HELPER_DIR="$helper_dir" \
SLOPTRAP_ACTIVE_CAPABILITIES="${SLOPTRAP_ACTIVE_CAPABILITIES:-}" \
SLOPTRAP_AUDIT_LOG="${SLOPTRAP_AUDIT_LOG:-/codex/state/capabilities.log}" \
SLOPTRAP_CAPTURE_DIR="${SLOPTRAP_CAPTURE_DIR:-/codex/state/captures}" \
SLOPTRAP_WORKDIR="${SLOPTRAP_WORKDIR:-/workspace}" \
SLOPTRAP_HOST_UID="${SLOPTRAP_HOST_UID:-$(id -u)}" \
SLOPTRAP_HOST_GID="${SLOPTRAP_HOST_GID:-$(id -g)}" \
bash -c '
set -euo pipefail
helper_dir=${SLOPTRAP_HELPER_DIR:-/tmp/sloptrap-helper}
queue_dir="$helper_dir/queue"
pidfile="$helper_dir/helperd.pid"
helper_bin=$(command -v sloptrap-helperd)
[[ -n $helper_bin ]] || exit 1
mkdir -p "$queue_dir"
chmod 711 "$helper_dir"
chmod 700 "$queue_dir"
chown "$SLOPTRAP_HOST_UID:$SLOPTRAP_HOST_GID" "$queue_dir"
if [[ -r $pidfile ]]; then
pid=$(<"$pidfile")
if [[ -n $pid ]] && kill -0 "$pid" 2>/dev/null; then
exit 0
fi
fi
"$helper_bin" >/dev/null 2>&1 &
for ((i=0; i<30; i+=1)); do
if [[ -r $pidfile ]]; then
pid=$(<"$pidfile")
if [[ -n $pid ]] && kill -0 "$pid" 2>/dev/null; then
exit 0
fi
fi
sleep 0.1
done
exit 1
'
}
resolve_requested_path() {
local raw=$1
if command -v realpath >/dev/null 2>&1; then
realpath -m "$raw"
return
fi
case "$raw" in
/*) printf '%s\n' "$raw" ;;
*) printf '%s/%s\n' "$(pwd -P)" "$raw" ;;
esac
}
validate_output_path() {
local path=$1
local resolved capture_root workspace_path
resolved=$(resolve_requested_path "$path")
capture_root=$(resolve_requested_path "$default_output")
workspace_path=$(resolve_requested_path "$workspace_root")
case "$resolved" in
"$capture_root"|"${capture_root}/"*|"$workspace_path"|"${workspace_path}/"*)
return 0
;;
esac
return 1
}
if [[ ${1-} != "capture" ]]; then if [[ ${1-} != "capture" ]]; then
printf 'usage: slopcap capture --interface <iface> [--filter <expr>] [--output <path>] [--stdout]\n' >&2 printf 'usage: slopcap capture --interface <iface> [--filter <expr>] [--output <path>] [--stdout]\n' >&2
@@ -633,6 +918,12 @@ done
if [[ -z $output && $stdout_mode -eq 0 ]]; then if [[ -z $output && $stdout_mode -eq 0 ]]; then
output="$default_output/capture-$(date +%s).pcap" output="$default_output/capture-$(date +%s).pcap"
fi fi
if [[ -n $output ]] && ! validate_output_path "$output"; then
printf 'slopcap: output path must stay within %s or %s\n' "$default_output" "$workspace_root" >&2
exit 2
fi
ensure_helper_ready
request_dir=$(mktemp -d "$queue_dir/request.XXXXXX.req") request_dir=$(mktemp -d "$queue_dir/request.XXXXXX.req")
trap 'rm -rf "$request_dir"' EXIT INT TERM HUP trap 'rm -rf "$request_dir"' EXIT INT TERM HUP
@@ -674,6 +965,19 @@ EOF
#!/usr/bin/env bash #!/usr/bin/env bash
set -euo pipefail set -euo pipefail
caps=${SLOPTRAP_ACTIVE_CAPABILITIES:-}
has_capability() {
local needle=$1
local token
for token in $caps; do
if [[ $token == "$needle" ]]; then
return 0
fi
done
return 1
}
if [[ $# -eq 0 ]]; then if [[ $# -eq 0 ]]; then
printf 'usage: sloppodman <pull|build|tag|run|ps|logs|stop|rm|inspect> ...\n' >&2 printf 'usage: sloppodman <pull|build|tag|run|ps|logs|stop|rm|inspect> ...\n' >&2
exit 2 exit 2
@@ -691,6 +995,11 @@ case "$subcommand" in
;; ;;
esac esac
has_capability "nested-podman" || {
printf 'sloppodman: capability nested-podman is not active\n' >&2
exit 126
}
workspace_root=${SLOPTRAP_WORKDIR:-/workspace} workspace_root=${SLOPTRAP_WORKDIR:-/workspace}
podman_root=${SLOPTRAP_INNER_PODMAN_ROOT:-/codex/capabilities/podman/storage} podman_root=${SLOPTRAP_INNER_PODMAN_ROOT:-/codex/capabilities/podman/storage}
podman_runroot=${SLOPTRAP_INNER_PODMAN_RUNROOT:-/codex/capabilities/podman/run} podman_runroot=${SLOPTRAP_INNER_PODMAN_RUNROOT:-/codex/capabilities/podman/run}
@@ -721,6 +1030,63 @@ validate_workspace_path() {
esac esac
} }
reject_flag() {
local flag=$1
printf 'sloppodman: %s is not permitted\n' "$flag" >&2
exit 2
}
validate_volume_spec() {
local spec=$1
local source
if [[ $spec != *:* ]]; then
return 0
fi
source=${spec%%:*}
case "$source" in
"" )
return 0
;;
.|..|/*|./*|../*|*/*)
validate_workspace_path "$source"
;;
* )
return 0
;;
esac
}
validate_mount_spec() {
local spec=$1
local type=""
local source=""
local part
IFS=',' read -r -a mount_parts <<< "$spec"
for part in "${mount_parts[@]}"; do
case "$part" in
type=*)
type=${part#type=}
;;
source=*|src=*)
source=${part#*=}
;;
esac
done
case "$type" in
volume|tmpfs)
return 0
;;
bind)
[[ -n $source ]] || reject_flag "--mount"
validate_workspace_path "$source"
return 0
;;
*)
reject_flag "--mount"
;;
esac
}
if [[ $subcommand == "build" ]]; then if [[ $subcommand == "build" ]]; then
args=("$@") args=("$@")
context="" context=""
@@ -733,6 +1099,9 @@ if [[ $subcommand == "build" ]]; then
(( idx < ${#args[@]} )) || { printf 'sloppodman: %s requires a path\n' "$arg" >&2; exit 2; } (( idx < ${#args[@]} )) || { printf 'sloppodman: %s requires a path\n' "$arg" >&2; exit 2; }
validate_workspace_path "${args[$idx]}" validate_workspace_path "${args[$idx]}"
;; ;;
--file=*)
validate_workspace_path "${arg#*=}"
;;
--network) --network)
((idx+=1)) ((idx+=1))
(( idx < ${#args[@]} )) || { printf 'sloppodman: --network requires a value\n' >&2; exit 2; } (( idx < ${#args[@]} )) || { printf 'sloppodman: --network requires a value\n' >&2; exit 2; }
@@ -741,6 +1110,15 @@ if [[ $subcommand == "build" ]]; then
exit 2 exit 2
fi fi
;; ;;
--network=*)
if [[ ${arg#*=} == "host" && ${SLOPTRAP_INNER_PODMAN_HOST_NETWORK:-0} != 1 ]]; then
printf 'sloppodman: host networking is not available in this session\n' >&2
exit 2
fi
;;
-v|--volume|--volume=*|--mount|--mount=*|--security-opt|--security-opt=*|--cap-add|--cap-add=*|--cap-drop|--cap-drop=*|--device|--device=*|--privileged|--privileged=*|--rootfs|--rootfs=*)
reject_flag "${arg%%=*}"
;;
esac esac
((idx+=1)) ((idx+=1))
done done
@@ -755,14 +1133,49 @@ if [[ $subcommand == "run" ]]; then
idx=0 idx=0
while (( idx < ${#args[@]} )); do while (( idx < ${#args[@]} )); do
arg=${args[$idx]} arg=${args[$idx]}
if [[ $arg == "--network" ]]; then case "$arg" in
((idx+=1)) --)
(( idx < ${#args[@]} )) || { printf 'sloppodman: --network requires a value\n' >&2; exit 2; } break
if [[ ${args[$idx]} == "host" && ${SLOPTRAP_INNER_PODMAN_HOST_NETWORK:-0} != 1 ]]; then ;;
printf 'sloppodman: host networking is not available in this session\n' >&2 --network)
exit 2 ((idx+=1))
fi (( idx < ${#args[@]} )) || { printf 'sloppodman: --network requires a value\n' >&2; exit 2; }
fi if [[ ${args[$idx]} == "host" && ${SLOPTRAP_INNER_PODMAN_HOST_NETWORK:-0} != 1 ]]; then
printf 'sloppodman: host networking is not available in this session\n' >&2
exit 2
fi
;;
--network=*)
if [[ ${arg#*=} == "host" && ${SLOPTRAP_INNER_PODMAN_HOST_NETWORK:-0} != 1 ]]; then
printf 'sloppodman: host networking is not available in this session\n' >&2
exit 2
fi
;;
-v|--volume)
((idx+=1))
(( idx < ${#args[@]} )) || { printf 'sloppodman: %s requires a value\n' "$arg" >&2; exit 2; }
validate_volume_spec "${args[$idx]}"
;;
--volume=*)
validate_volume_spec "${arg#*=}"
;;
--mount)
((idx+=1))
(( idx < ${#args[@]} )) || { printf 'sloppodman: --mount requires a value\n' >&2; exit 2; }
validate_mount_spec "${args[$idx]}"
;;
--mount=*)
validate_mount_spec "${arg#*=}"
;;
--privileged|--privileged=*|--cap-add|--cap-add=*|--cap-drop|--cap-drop=*|--device|--device=*|--security-opt|--security-opt=*|--rootfs|--rootfs=*|--pid|--pid=*|--ipc|--ipc=*|--uts|--uts=*|--userns|--userns=*|--cgroupns|--cgroupns=*)
reject_flag "${arg%%=*}"
;;
-*)
;;
*)
break
;;
esac
((idx+=1)) ((idx+=1))
done done
fi fi
@@ -880,6 +1293,11 @@ ensure_capability_state_paths() {
ensure_codex_directory "$CAPABILITY_TRUST_ROOT_HOST" "sloptrap capability trust root" ensure_codex_directory "$CAPABILITY_TRUST_ROOT_HOST" "sloptrap capability trust root"
ensure_codex_directory "$(dirname "$CAPABILITY_BUILD_STAMP_HOST")" "sloptrap capability build stamp root" ensure_codex_directory "$(dirname "$CAPABILITY_BUILD_STAMP_HOST")" "sloptrap capability build stamp root"
ensure_codex_directory "$CAPABILITY_STATE_HOST" "project capability state" ensure_codex_directory "$CAPABILITY_STATE_HOST" "project capability state"
if capability_list_contains "$REQUESTED_CAPABILITIES" "nested-podman"; then
ensure_codex_directory "$CAPABILITY_STATE_HOST/podman-storage" "nested podman storage state"
ensure_codex_directory "$CAPABILITY_STATE_HOST/podman-run" "nested podman runroot state"
ensure_codex_directory "$CAPABILITY_STATE_HOST/podman-runtime" "nested podman runtime state"
fi
} }
capability_trust_matches_current() { capability_trust_matches_current() {
@@ -1189,7 +1607,7 @@ validate_package_list() {
[[ -z $raw ]] && return 0 [[ -z $raw ]] && return 0
local token local token
for token in $raw; do for token in $raw; do
if [[ ! $token =~ ^[A-Za-z0-9+.-]+$ ]]; then if [[ ! $token =~ ^[A-Za-z0-9][A-Za-z0-9+.-]*$ ]]; then
error "$source: invalid package name '$token' in '$key'" error "$source: invalid package name '$token' in '$key'"
fi fi
done done
@@ -1465,16 +1883,7 @@ print_manifest_summary() {
} }
build_runtime_context_prompt() { build_runtime_context_prompt() {
local manifest_present prompt manifest_capabilities trusted enabled network_mode local prompt enabled network_mode
manifest_present="false"
if [[ -f $MANIFEST_PATH ]]; then
manifest_present="true"
fi
manifest_capabilities=${REQUESTED_CAPABILITIES:-none}
trusted="none"
if [[ -n $REQUESTED_CAPABILITIES ]] && capability_trust_matches_current; then
trusted=$REQUESTED_CAPABILITIES
fi
enabled=${ENABLED_CAPABILITIES:-none} enabled=${ENABLED_CAPABILITIES:-none}
network_mode="isolated" network_mode="isolated"
if [[ $SLOPTRAP_NETWORK_NAME == "host" ]]; then if [[ $SLOPTRAP_NETWORK_NAME == "host" ]]; then
@@ -1484,28 +1893,11 @@ build_runtime_context_prompt() {
You are running inside sloptrap, which confines Codex inside a container. You are running inside sloptrap, which confines Codex inside a container.
This startup note describes the sloptrap runtime only; it does not replace higher-priority instructions from AGENTS.md or the system. This startup note describes the sloptrap runtime only; it does not replace higher-priority instructions from AGENTS.md or the system.
Container layout:
- /workspace is the project mount.
- /codex is persistent Codex state for this project.
- The project manifest path is /workspace/.sloptrap and it may be absent.
Manifest key meanings:
- name: labels the sloptrap project/image/container names.
- packages_extra: Debian packages added when the image was built.
- capabilities: privileged features requested by the manifest; only capabilities enabled for this run are currently usable.
- allow_host_network: enables host networking when true; otherwise networking is isolated.
Current resolved sloptrap state: Current resolved sloptrap state:
- manifest_present=$manifest_present - name=$PROJECT_NAME (project/image/container label)
- project_name=$PROJECT_NAME - packages_extra=${PACKAGES_EXTRA:-none} (Debian packages added at build time)
- packages_extra=${PACKAGES_EXTRA:-none} - enabled_capabilities=$enabled (privileged features usable in this run)
- manifest_capabilities=$manifest_capabilities - network_mode=$network_mode (host when host networking is enabled; otherwise isolated)
- trusted_capabilities=$trusted
- enabled_capabilities=$enabled
- network_mode=$network_mode
- runtime_flags=$CODEX_ARGS_DISPLAY
If you need exact project configuration, inspect /workspace/.sloptrap directly.
EOF EOF
) )
printf '%s' "$prompt" printf '%s' "$prompt"
@@ -1785,7 +2177,7 @@ prepare_container_runtime() {
SLOPTRAP_PACKAGES_CAPABILITY+=" tcpdump" SLOPTRAP_PACKAGES_CAPABILITY+=" tcpdump"
fi fi
if capability_list_contains "$REQUESTED_CAPABILITIES" "nested-podman"; then if capability_list_contains "$REQUESTED_CAPABILITIES" "nested-podman"; then
SLOPTRAP_PACKAGES_CAPABILITY+=" podman fuse-overlayfs slirp4netns" SLOPTRAP_PACKAGES_CAPABILITY+=" podman uidmap fuse-overlayfs slirp4netns"
fi fi
SLOPTRAP_PACKAGES_CAPABILITY=$(normalize_package_list "$SLOPTRAP_PACKAGES_CAPABILITY") SLOPTRAP_PACKAGES_CAPABILITY=$(normalize_package_list "$SLOPTRAP_PACKAGES_CAPABILITY")
local default_codex_archive local default_codex_archive
@@ -1877,6 +2269,15 @@ prepare_container_runtime() {
if capability_list_contains "$ENABLED_CAPABILITIES" "nested-podman"; then if capability_list_contains "$ENABLED_CAPABILITIES" "nested-podman"; then
capability_opts+=(--device /dev/fuse) capability_opts+=(--device /dev/fuse)
fi fi
if $SLOPTRAP_RUN_AS_ROOT; then
capability_opts+=(
--cap-add SETUID
--cap-add SETGID
--cap-add CHOWN
--cap-add DAC_OVERRIDE
--cap-add FOWNER
)
fi
local rootfs_flag=() local rootfs_flag=()
case "${SLOPTRAP_ROOTFS_READONLY,,}" in case "${SLOPTRAP_ROOTFS_READONLY,,}" in
@@ -1911,7 +2312,7 @@ prepare_container_runtime() {
-e "XDG_STATE_HOME=$SLOPTRAP_CODEX_HOME_CONT/state" -e "XDG_STATE_HOME=$SLOPTRAP_CODEX_HOME_CONT/state"
-e "CODEX_HOME=$SLOPTRAP_CODEX_HOME_CONT" -e "CODEX_HOME=$SLOPTRAP_CODEX_HOME_CONT"
-e "SLOPTRAP_WORKDIR=$SLOPTRAP_WORKDIR" -e "SLOPTRAP_WORKDIR=$SLOPTRAP_WORKDIR"
-e "SLOPTRAP_HELPER_DIR=/run/sloptrap-helper" -e "SLOPTRAP_HELPER_DIR=/tmp/sloptrap-helper"
-e "SLOPTRAP_ACTIVE_CAPABILITIES=$ENABLED_CAPABILITIES" -e "SLOPTRAP_ACTIVE_CAPABILITIES=$ENABLED_CAPABILITIES"
-e "SLOPTRAP_CAPTURE_DIR=$SLOPTRAP_CODEX_HOME_CONT/state/captures" -e "SLOPTRAP_CAPTURE_DIR=$SLOPTRAP_CODEX_HOME_CONT/state/captures"
-e "SLOPTRAP_AUDIT_LOG=$SLOPTRAP_CODEX_HOME_CONT/state/capabilities.log" -e "SLOPTRAP_AUDIT_LOG=$SLOPTRAP_CODEX_HOME_CONT/state/capabilities.log"
@@ -1926,12 +2327,19 @@ prepare_container_runtime() {
local uid gid local uid gid
uid=$(id -u) uid=$(id -u)
gid=$(id -g) gid=$(id -g)
env_args+=(
-e "SLOPTRAP_HOST_UID=$uid"
-e "SLOPTRAP_HOST_GID=$gid"
)
local -a user_opts=("--user" "$uid:$gid") local -a user_opts=("--user" "$uid:$gid")
if [[ $CONTAINER_ENGINE == "podman" ]]; then if [[ $CONTAINER_ENGINE == "podman" ]]; then
user_opts=(--userns="keep-id:uid=$uid,gid=$gid" "${user_opts[@]}") user_opts=(--userns="keep-id:uid=$uid,gid=$gid" "${user_opts[@]}")
fi fi
if $SLOPTRAP_RUN_AS_ROOT; then if $SLOPTRAP_RUN_AS_ROOT; then
user_opts=() user_opts=()
if [[ $CONTAINER_ENGINE == "podman" ]]; then
user_opts=(--userns="keep-id:uid=$uid,gid=$gid")
fi
fi fi
CONTAINER_SHARED_OPTS=( CONTAINER_SHARED_OPTS=(

View File

@@ -211,6 +211,33 @@ teardown_stub_env() {
rm -f "${STUB_LOG:-}" rm -f "${STUB_LOG:-}"
} }
extract_embedded_helper() {
local helper=$1
local output=$2
if ! awk -v helper="$helper" '
$0 ~ "^[[:space:]]*" helper "\\)$" { state=1; next }
state == 1 && /cat <<'\''EOF'\''$/ { state=2; next }
state == 2 && /^EOF$/ { exit }
state == 2 { print }
' "$SLOPTRAP_BIN" >"$output"; then
return 1
fi
chmod +x "$output"
}
wait_for_path() {
local path=$1
local attempts=${2:-100}
while (( attempts > 0 )); do
if [[ -e $path ]]; then
return 0
fi
sleep 0.1
((attempts-=1))
done
return 1
}
record_failure() { record_failure() {
failures+=("$1") failures+=("$1")
} }
@@ -302,6 +329,22 @@ run_secret_mask() {
teardown_stub_env teardown_stub_env
} }
run_git_ignore_mask() {
local scenario_dir="$ROOT_DIR"
printf '==> git_ignore_mask\n'
setup_stub_env
if ! PATH="$STUB_BIN:$PATH" HOME="$STUB_HOME" FAKE_PODMAN_LOG="$STUB_LOG" FAKE_PODMAN_INSPECT_FAIL=1 \
"$SLOPTRAP_BIN" --trust-capabilities "$scenario_dir" </dev/null >/dev/null 2>&1; then
record_failure "git_ignore_mask: sloptrap exited non-zero"
teardown_stub_env
return
fi
if ! grep -q -- "--mount type=tmpfs,target=/workspace/.git" "$STUB_LOG"; then
record_failure "git_ignore_mask: .git was not masked with tmpfs"
fi
teardown_stub_env
}
run_resume_target() { run_resume_target() {
local scenario_dir="$TEST_ROOT/resume_target" local scenario_dir="$TEST_ROOT/resume_target"
printf '==> resume_target\n' printf '==> resume_target\n'
@@ -335,10 +378,9 @@ run_runtime_context_prompt() {
if [[ -z $run_line || $run_line != *"You are running inside sloptrap"* ]]; then if [[ -z $run_line || $run_line != *"You are running inside sloptrap"* ]]; then
record_failure "runtime_context_prompt: startup prompt missing from fresh run" record_failure "runtime_context_prompt: startup prompt missing from fresh run"
fi fi
if ! grep -q -- "manifest_present=true" "$STUB_LOG" \ if ! grep -q -- "name=capability-repo" "$STUB_LOG" \
|| ! grep -q -- "manifest_capabilities=apt-install nested-podman packet-capture" "$STUB_LOG" \ || ! grep -q -- "enabled_capabilities=apt-install nested-podman packet-capture" "$STUB_LOG" \
|| ! grep -q -- "trusted_capabilities=apt-install nested-podman packet-capture" "$STUB_LOG" \ || ! grep -q -- "network_mode=host" "$STUB_LOG"; then
|| ! grep -q -- "enabled_capabilities=apt-install nested-podman packet-capture" "$STUB_LOG"; then
record_failure "runtime_context_prompt: runtime summary missing manifest or capability state" record_failure "runtime_context_prompt: runtime summary missing manifest or capability state"
fi fi
if [[ -n $login_line && $login_line == *"You are running inside sloptrap"* ]]; then if [[ -n $login_line && $login_line == *"You are running inside sloptrap"* ]]; then
@@ -690,7 +732,7 @@ run_capability_profiles() {
teardown_stub_env teardown_stub_env
return return
fi fi
if ! grep -q -- "CAPABILITY_PACKAGES=tcpdump podman fuse-overlayfs slirp4netns" "$STUB_LOG"; then if ! grep -q -- "CAPABILITY_PACKAGES=tcpdump podman uidmap fuse-overlayfs slirp4netns" "$STUB_LOG"; then
record_failure "capability_profiles: build arg for capability packages missing" record_failure "capability_profiles: build arg for capability packages missing"
fi fi
if ! grep -q -- "--cap-add NET_RAW" "$STUB_LOG"; then if ! grep -q -- "--cap-add NET_RAW" "$STUB_LOG"; then
@@ -702,21 +744,279 @@ run_capability_profiles() {
if ! grep -q -- "--device /dev/fuse" "$STUB_LOG"; then if ! grep -q -- "--device /dev/fuse" "$STUB_LOG"; then
record_failure "capability_profiles: /dev/fuse device missing" record_failure "capability_profiles: /dev/fuse device missing"
fi fi
if ! grep -q -- "--cap-add SETUID" "$STUB_LOG"; then
record_failure "capability_profiles: SETUID capability missing"
fi
if ! grep -q -- "--cap-add SETGID" "$STUB_LOG"; then
record_failure "capability_profiles: SETGID capability missing"
fi
if ! grep -q -- "--cap-add CHOWN" "$STUB_LOG"; then
record_failure "capability_profiles: CHOWN capability missing"
fi
if ! grep -q -- "--cap-add DAC_OVERRIDE" "$STUB_LOG"; then
record_failure "capability_profiles: DAC_OVERRIDE capability missing"
fi
if ! grep -q -- "--cap-add FOWNER" "$STUB_LOG"; then
record_failure "capability_profiles: FOWNER capability missing"
fi
if grep -q -- "--read-only" "$STUB_LOG"; then if grep -q -- "--read-only" "$STUB_LOG"; then
record_failure "capability_profiles: apt profile should disable read-only rootfs" record_failure "capability_profiles: apt profile should disable read-only rootfs"
fi fi
if grep -q -- "--user " "$STUB_LOG"; then if grep -q -- "--user " "$STUB_LOG"; then
record_failure "capability_profiles: capability-enabled run should not force --user" record_failure "capability_profiles: capability-enabled run should not force --user"
fi fi
if ! grep -q -- "--userns=keep-id:uid=$(id -u),gid=$(id -g)" "$STUB_LOG"; then
record_failure "capability_profiles: podman keep-id user namespace missing"
fi
if ! grep -q -- "SLOPTRAP_ACTIVE_CAPABILITIES=apt-install nested-podman packet-capture" "$STUB_LOG"; then if ! grep -q -- "SLOPTRAP_ACTIVE_CAPABILITIES=apt-install nested-podman packet-capture" "$STUB_LOG"; then
record_failure "capability_profiles: active capability environment missing" record_failure "capability_profiles: active capability environment missing"
fi fi
if ! grep -q -- "SLOPTRAP_HOST_UID=$(id -u)" "$STUB_LOG"; then
record_failure "capability_profiles: host uid environment missing"
fi
if ! grep -q -- "SLOPTRAP_HOST_GID=$(id -g)" "$STUB_LOG"; then
record_failure "capability_profiles: host gid environment missing"
fi
if ! grep -q -- "SLOPTRAP_INNER_PODMAN_HOST_NETWORK=1" "$STUB_LOG"; then if ! grep -q -- "SLOPTRAP_INNER_PODMAN_HOST_NETWORK=1" "$STUB_LOG"; then
record_failure "capability_profiles: inner podman host-network mirror flag missing" record_failure "capability_profiles: inner podman host-network mirror flag missing"
fi fi
local state_root capability_dir
state_root="$STUB_HOME/.codex/sloptrap/state"
capability_dir=$(find "$state_root" -mindepth 2 -maxdepth 2 -type d -name capabilities | head -n 1 || true)
if [[ -z $capability_dir ]]; then
record_failure "capability_profiles: project capability state directory missing"
else
if [[ ! -d $capability_dir/podman-storage ]]; then
record_failure "capability_profiles: nested podman storage state missing"
fi
if [[ ! -d $capability_dir/podman-run ]]; then
record_failure "capability_profiles: nested podman runroot state missing"
fi
if [[ ! -d $capability_dir/podman-runtime ]]; then
record_failure "capability_profiles: nested podman runtime state missing"
fi
fi
teardown_stub_env teardown_stub_env
} }
run_embedded_capability_helpers() {
printf '==> embedded_capability_helpers\n'
local temp_root helper_bin helper_dir workspace_dir capture_dir tool_log helper_pid
local inner_podman_root inner_podman_runroot inner_runtime_dir
temp_root=$(mktemp -d)
helper_bin="$temp_root/bin"
helper_dir="$temp_root/helper"
workspace_dir="$temp_root/workspace"
capture_dir="$temp_root/captures"
tool_log="$temp_root/tool.log"
inner_podman_root="$temp_root/podman-storage"
inner_podman_runroot="$temp_root/podman-run"
inner_runtime_dir="$temp_root/podman-runtime"
helper_pid=""
mkdir -p "$helper_bin" "$helper_dir/queue" "$workspace_dir/data" "$capture_dir" \
"$inner_podman_root" "$inner_podman_runroot" "$inner_runtime_dir"
: >"$tool_log"
if ! extract_embedded_helper "sloptrap-entrypoint" "$helper_bin/sloptrap-entrypoint" \
|| ! extract_embedded_helper "sloptrap-helperd" "$helper_bin/sloptrap-helperd" \
|| ! extract_embedded_helper "slop-apt" "$helper_bin/slop-apt" \
|| ! extract_embedded_helper "slopcap" "$helper_bin/slopcap" \
|| ! extract_embedded_helper "sloppodman" "$helper_bin/sloppodman"; then
record_failure "embedded_capability_helpers: failed to extract embedded helper scripts"
rm -rf "$temp_root"
return
fi
cat >"$helper_bin/podman" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
printf 'podman %s\n' "$*" >>"$TEST_TOOL_LOG"
exit 0
EOF
cat >"$helper_bin/apt-get" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
printf 'apt-get %s\n' "$*" >>"$TEST_TOOL_LOG"
exit 0
EOF
cat >"$helper_bin/tcpdump" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
printf 'tcpdump %s\n' "$*" >>"$TEST_TOOL_LOG"
output=""
prev=""
for arg in "$@"; do
if [[ $prev == "-w" ]]; then
output=$arg
break
fi
prev=$arg
done
if [[ -n $output ]]; then
mkdir -p "$(dirname "$output")"
: >"$output"
fi
exit 0
EOF
cat >"$helper_bin/setpriv" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
while [[ $# -gt 0 ]]; do
case "$1" in
--reuid|--regid)
shift 2
;;
--clear-groups)
shift
;;
--)
shift
break
;;
*)
break
;;
esac
done
exec "$@"
EOF
chmod +x "$helper_bin/podman" "$helper_bin/apt-get" "$helper_bin/tcpdump" "$helper_bin/setpriv"
if ! grep -q "chmod 711 \"\\\$helper_dir\"" "$helper_bin/sloptrap-entrypoint" \
|| ! grep -q "chown \"\\\$target_uid:\\\$target_gid\" \"\\\$queue_dir\"" "$helper_bin/sloptrap-entrypoint"; then
record_failure "embedded_capability_helpers: entrypoint did not expose helper queue to the dropped user"
fi
local autostart_helper_dir
autostart_helper_dir="$temp_root/helper-autostart"
if ! TEST_TOOL_LOG="$tool_log" PATH="$helper_bin:$PATH" SLOPTRAP_HELPER_DIR="$autostart_helper_dir" \
SLOPTRAP_ACTIVE_CAPABILITIES="apt-install packet-capture" \
SLOPTRAP_CAPTURE_DIR="$capture_dir" SLOPTRAP_WORKDIR="$workspace_dir" \
SLOPTRAP_AUDIT_LOG="$temp_root/autostart-audit.log" \
SLOPTRAP_HOST_UID="$(id -u)" SLOPTRAP_HOST_GID="$(id -g)" \
"$helper_bin/slop-apt" install jq >/dev/null 2>&1; then
record_failure "embedded_capability_helpers: slop-apt did not self-bootstrap the helper daemon"
fi
if [[ ! -r $autostart_helper_dir/helperd.pid ]]; then
record_failure "embedded_capability_helpers: helper self-bootstrap did not create a pid file"
else
kill "$(cat "$autostart_helper_dir/helperd.pid")" >/dev/null 2>&1 || true
wait "$(cat "$autostart_helper_dir/helperd.pid")" >/dev/null 2>&1 || true
fi
local missing_cap_status=0
if TEST_TOOL_LOG="$tool_log" PATH="$helper_bin:$PATH" SLOPTRAP_ACTIVE_CAPABILITIES="" \
SLOPTRAP_WORKDIR="$workspace_dir" \
SLOPTRAP_INNER_PODMAN_ROOT="$inner_podman_root" \
SLOPTRAP_INNER_PODMAN_RUNROOT="$inner_podman_runroot" \
XDG_RUNTIME_DIR="$inner_runtime_dir" \
"$helper_bin/sloppodman" ps >/dev/null 2>&1; then
record_failure "embedded_capability_helpers: sloppodman should reject runs without nested-podman"
else
missing_cap_status=$?
fi
if [[ $missing_cap_status -ne 126 ]]; then
record_failure "embedded_capability_helpers: sloppodman returned the wrong status when capability was absent"
fi
if TEST_TOOL_LOG="$tool_log" PATH="$helper_bin:$PATH" SLOPTRAP_ACTIVE_CAPABILITIES="nested-podman" \
SLOPTRAP_WORKDIR="$workspace_dir" \
SLOPTRAP_INNER_PODMAN_ROOT="$inner_podman_root" \
SLOPTRAP_INNER_PODMAN_RUNROOT="$inner_podman_runroot" \
XDG_RUNTIME_DIR="$inner_runtime_dir" \
"$helper_bin/sloppodman" run --privileged example/image >/dev/null 2>&1; then
record_failure "embedded_capability_helpers: sloppodman allowed --privileged"
fi
if TEST_TOOL_LOG="$tool_log" PATH="$helper_bin:$PATH" SLOPTRAP_ACTIVE_CAPABILITIES="nested-podman" \
SLOPTRAP_WORKDIR="$workspace_dir" \
SLOPTRAP_INNER_PODMAN_ROOT="$inner_podman_root" \
SLOPTRAP_INNER_PODMAN_RUNROOT="$inner_podman_runroot" \
XDG_RUNTIME_DIR="$inner_runtime_dir" \
"$helper_bin/sloppodman" run -v /tmp:/host example/image >/dev/null 2>&1; then
record_failure "embedded_capability_helpers: sloppodman allowed an out-of-workspace bind mount"
fi
if ! (
cd "$workspace_dir" && TEST_TOOL_LOG="$tool_log" PATH="$helper_bin:$PATH" \
SLOPTRAP_ACTIVE_CAPABILITIES="nested-podman" SLOPTRAP_WORKDIR="$workspace_dir" \
SLOPTRAP_INNER_PODMAN_ROOT="$inner_podman_root" \
SLOPTRAP_INNER_PODMAN_RUNROOT="$inner_podman_runroot" \
XDG_RUNTIME_DIR="$inner_runtime_dir" \
"$helper_bin/sloppodman" run -v ./data:/data example/image true >/dev/null 2>&1
); then
record_failure "embedded_capability_helpers: sloppodman rejected a workspace-local bind mount"
fi
if ! grep -q -- 'podman --root ' "$tool_log" || ! grep -q -- '-v ./data:/data' "$tool_log"; then
record_failure "embedded_capability_helpers: sloppodman did not invoke podman with the validated run arguments"
fi
TEST_TOOL_LOG="$tool_log" PATH="$helper_bin:$PATH" SLOPTRAP_HELPER_DIR="$helper_dir" \
SLOPTRAP_ACTIVE_CAPABILITIES="apt-install packet-capture" \
SLOPTRAP_CAPTURE_DIR="$capture_dir" SLOPTRAP_WORKDIR="$workspace_dir" \
SLOPTRAP_AUDIT_LOG="$temp_root/audit.log" "$helper_bin/sloptrap-helperd" >/dev/null 2>&1 &
helper_pid=$!
if ! TEST_TOOL_LOG="$tool_log" PATH="$helper_bin:$PATH" SLOPTRAP_HELPER_DIR="$helper_dir" \
"$helper_bin/slop-apt" install jq >/dev/null 2>&1; then
record_failure "embedded_capability_helpers: slop-apt failed against the embedded helper daemon"
fi
if ! grep -q -- 'apt-get install -y --no-install-recommends jq' "$tool_log"; then
record_failure "embedded_capability_helpers: slop-apt did not reach apt-get install"
fi
local bad_apt_request
bad_apt_request=$(mktemp -d "$helper_dir/queue/request.XXXXXX.req")
printf 'apt-install\n' >"$bad_apt_request/op"
printf '%s\n' '--allow-unauthenticated' >"$bad_apt_request/packages"
if ! wait_for_path "$bad_apt_request/status"; then
record_failure "embedded_capability_helpers: helper daemon did not answer the invalid apt request"
elif [[ $(<"$bad_apt_request/status") != "2" ]]; then
record_failure "embedded_capability_helpers: invalid apt request returned the wrong status"
fi
if [[ -s "$bad_apt_request/stderr" ]] && ! grep -q -- 'invalid package name' "$bad_apt_request/stderr"; then
record_failure "embedded_capability_helpers: invalid apt request did not explain the rejection"
fi
if TEST_TOOL_LOG="$tool_log" PATH="$helper_bin:$PATH" SLOPTRAP_HELPER_DIR="$helper_dir" \
SLOPTRAP_CAPTURE_DIR="$capture_dir" SLOPTRAP_WORKDIR="$workspace_dir" \
"$helper_bin/slopcap" capture --interface eth0 --output /tmp/escape.pcap >/dev/null 2>&1; then
record_failure "embedded_capability_helpers: slopcap accepted an out-of-bounds output path"
fi
if ! TEST_TOOL_LOG="$tool_log" PATH="$helper_bin:$PATH" SLOPTRAP_HELPER_DIR="$helper_dir" \
SLOPTRAP_CAPTURE_DIR="$capture_dir" SLOPTRAP_WORKDIR="$workspace_dir" \
"$helper_bin/slopcap" capture --interface eth0 --filter 'tcp port 80' \
--output "$workspace_dir/capture.pcap" >/dev/null 2>&1; then
record_failure "embedded_capability_helpers: slopcap failed for a workspace-local capture file"
fi
if ! grep -q -- "tcpdump -i eth0 -w $workspace_dir/capture.pcap -- tcp port 80" "$tool_log"; then
record_failure "embedded_capability_helpers: slopcap did not invoke tcpdump with the expected guarded arguments"
fi
local bad_capture_request
bad_capture_request=$(mktemp -d "$helper_dir/queue/request.XXXXXX.req")
printf 'packet-capture\n' >"$bad_capture_request/op"
printf 'eth0\n' >"$bad_capture_request/interface"
printf '\n' >"$bad_capture_request/filter"
printf '/tmp/escape.pcap\n' >"$bad_capture_request/output"
printf '0\n' >"$bad_capture_request/stdout_mode"
if ! wait_for_path "$bad_capture_request/status"; then
record_failure "embedded_capability_helpers: helper daemon did not answer the invalid capture request"
elif [[ $(<"$bad_capture_request/status") != "2" ]]; then
record_failure "embedded_capability_helpers: invalid capture request returned the wrong status"
fi
if [[ -s "$bad_capture_request/stderr" ]] && ! grep -q -- 'output path must stay within' "$bad_capture_request/stderr"; then
record_failure "embedded_capability_helpers: invalid capture request did not explain the rejection"
fi
if [[ -n $helper_pid ]]; then
kill "$helper_pid" >/dev/null 2>&1 || true
wait "$helper_pid" >/dev/null 2>&1 || true
fi
rm -rf "$temp_root"
}
run_make_install_single_file() { run_make_install_single_file() {
local scenario_dir="$TEST_ROOT/resume_target" local scenario_dir="$TEST_ROOT/resume_target"
printf '==> make_install_single_file\n' printf '==> make_install_single_file\n'
@@ -768,6 +1068,7 @@ run_symlink_escape
run_manifest_injection run_manifest_injection
run_helper_symlink run_helper_symlink
run_secret_mask run_secret_mask
run_git_ignore_mask
run_resume_target run_resume_target
run_runtime_context_prompt run_runtime_context_prompt
run_sh_reexec run_sh_reexec
@@ -791,6 +1092,7 @@ run_wizard_existing_defaults
run_wizard_build_trigger run_wizard_build_trigger
run_capability_trust_required run_capability_trust_required
run_capability_profiles run_capability_profiles
run_embedded_capability_helpers
run_make_install_single_file run_make_install_single_file
if [[ ${#failures[@]} -gt 0 ]]; then if [[ ${#failures[@]} -gt 0 ]]; then