Files
coredesktop/configure.d/65-sandbox.sh
T
david 1d9d759fb1
shellcheck / shellcheck (push) Failing after 16s
Turn off Winboat container and do some sandboxing
2026-11-02 09:05:22 -07:00

84 lines
2.8 KiB
Bash

#!/bin/bash
# configure reads TITLE and DESCRIPTION
# shellcheck disable=SC2034
TITLE="Agent sandbox"
# shellcheck disable=SC2034
DESCRIPTION="Choose what agents may read, e.g. WinBoat's settings"
# The sandbox config every sandboxed agent reads (see sandbox/agent)
SANDBOX_CONF="$HOME/.config/coredesktop/sandbox/base.json"
source "$COREDESKTOP/configure.d/lib/json.sh"
# Folders the sandbox hides from agents (sandbox/config/base.json) that you
# may let them read: "path|what it is". Your SSH keys, password stores,
# browsers and the like aren't here; they're always hidden. A path in
# allowRead can be read even inside one in denyRead, so letting agents read
# one is adding it to allowRead in your own config.
# The paths are written as in sandbox/config/base.json, with ~ for srt to expand
# shellcheck disable=SC2088
OPTIONAL_HIDDEN=(
"~/.winboat|WinBoat's settings, which include your Windows password"
)
# Offered only when one of the folders is on this machine
is_installed() {
local entry path
for entry in "${OPTIONAL_HIDDEN[@]}"; do
path="${entry%%|*}"
[ -e "${path/#\~/$HOME}" ] && return 0
done
return 1
}
# Hiding them is the default, so there's nothing you need to do
is_configured() {
true
}
# True if agents may read $1 (it's in your config's allowRead)
readable() {
jq -e --arg path "$1" '.filesystem.allowRead // [] | index($path)' "$SANDBOX_CONF" &> /dev/null
}
let_read() {
edit_json "$SANDBOX_CONF" '{}' --arg path "$1" \
'.filesystem.allowRead = ((.filesystem.allowRead // []) - [$path] + [$path])'
}
hide() {
[ -f "$SANDBOX_CONF" ] || return 0
edit_json "$SANDBOX_CONF" '{}' --arg path "$1" \
'if .filesystem.allowRead then .filesystem.allowRead -= [$path] else . end'
}
run_configure() {
local choice i path what state
echo "Agents in the sandbox can't read these unless you let them. Changes apply the next"
echo "time you start an agent (restart Hermes' gateway with: systemctl --user restart hermes-gateway)."
echo "Claude Code's own sandbox doesn't use this list."
while true; do
echo
for i in "${!OPTIONAL_HIDDEN[@]}"; do
IFS='|' read -r path what <<< "${OPTIONAL_HIDDEN[$i]}"
if readable "$path"; then state="\e[33magents can read it\e[0m"; else state="\e[32mhidden\e[0m"; fi
printf " %d) %-12s $state %s\n" $((i + 1)) "$path" "$what"
done
echo " q) Done"
echo
read -rp "Choose one to switch: " choice || return 0
if ! [[ "$choice" =~ ^[0-9]+$ ]] || (( choice < 1 || choice > ${#OPTIONAL_HIDDEN[@]} )); then
return 0
fi
IFS='|' read -r path what <<< "${OPTIONAL_HIDDEN[$((choice - 1))]}"
if readable "$path"; then
hide "$path" || return 1
echo "$path is hidden from agents again."
elif confirm "Let agents read $path ($what)?"; then
let_read "$path" || return 1
echo "Agents can read $path."
fi
done
}