From 750981529bfabf54a795d778cf71187b7dea0543 Mon Sep 17 00:00:00 2001 From: Agent Date: Mon, 20 Apr 2026 17:46:35 +0000 Subject: [PATCH] fix: tools/edge-control/verify-chat-sandbox.sh targets deleted disinto-chat container (#1087) Co-Authored-By: Claude Opus 4.6 --- AGENTS.md | 2 +- tools/edge-control/verify-chat-sandbox.sh | 113 ---------------------- 2 files changed, 1 insertion(+), 114 deletions(-) delete mode 100755 tools/edge-control/verify-chat-sandbox.sh diff --git a/AGENTS.md b/AGENTS.md index efdfc3e..eb28305 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -43,7 +43,7 @@ disinto/ (code repo) ├── projects/ *.toml.example — templates; *.toml — local per-box config (gitignored) ├── formulas/ Issue templates (TOML specs for multi-step agent tasks) ├── docker/ Dockerfiles and entrypoints: reproduce, triage, edge (Caddy + chat server subprocess + dispatcher), chat (server.py, ui/ — copied into edge image at build time) -├── tools/ Operational tools: edge-control/ (register.sh, install.sh, verify-chat-sandbox.sh) +├── tools/ Operational tools: edge-control/ (register.sh, install.sh) │ vault-apply-policies.sh, vault-apply-roles.sh, vault-import.sh — Vault provisioning (S2.1/S2.2) │ vault-seed-.sh — per-service Vault secret seeders; auto-invoked by `bin/disinto --with ` (add a new file to support a new service) ├── docs/ Protocol docs (PHASE-PROTOCOL.md, EVIDENCE-ARCHITECTURE.md) diff --git a/tools/edge-control/verify-chat-sandbox.sh b/tools/edge-control/verify-chat-sandbox.sh deleted file mode 100755 index 245d1da..0000000 --- a/tools/edge-control/verify-chat-sandbox.sh +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# verify-chat-sandbox.sh — One-shot sandbox verification for disinto-chat (#706) -# -# Runs against a live compose project and asserts hardening constraints. -# Exit 0 if all pass, non-zero otherwise. - -CONTAINER="disinto-chat" -PASS=0 -FAIL=0 - -pass() { printf ' ✓ %s\n' "$1"; PASS=$((PASS + 1)); } -fail() { printf ' ✗ %s\n' "$1"; FAIL=$((FAIL + 1)); } - -echo "=== disinto-chat sandbox verification ===" -echo - -# --- docker inspect checks --- - -inspect_json=$(docker inspect "$CONTAINER" 2>/dev/null) || { - echo "ERROR: container '$CONTAINER' not found or not running" - exit 1 -} - -# ReadonlyRootfs -readonly_rootfs=$(echo "$inspect_json" | python3 -c "import sys,json; print(json.load(sys.stdin)[0]['HostConfig']['ReadonlyRootfs'])") -if [ "$readonly_rootfs" = "True" ]; then - pass "ReadonlyRootfs=true" -else - fail "ReadonlyRootfs expected true, got $readonly_rootfs" -fi - -# CapAdd — should be null or empty -cap_add=$(echo "$inspect_json" | python3 -c "import sys,json; print(json.load(sys.stdin)[0]['HostConfig']['CapAdd'])") -if [ "$cap_add" = "None" ] || [ "$cap_add" = "[]" ]; then - pass "CapAdd=null (no extra capabilities)" -else - fail "CapAdd expected null, got $cap_add" -fi - -# CapDrop — should contain ALL -cap_drop=$(echo "$inspect_json" | python3 -c "import sys,json; caps=json.load(sys.stdin)[0]['HostConfig']['CapDrop'] or []; print(' '.join(caps))") -if echo "$cap_drop" | grep -q "ALL"; then - pass "CapDrop contains ALL" -else - fail "CapDrop expected ALL, got: $cap_drop" -fi - -# PidsLimit -pids_limit=$(echo "$inspect_json" | python3 -c "import sys,json; print(json.load(sys.stdin)[0]['HostConfig']['PidsLimit'])") -if [ "$pids_limit" = "128" ]; then - pass "PidsLimit=128" -else - fail "PidsLimit expected 128, got $pids_limit" -fi - -# Memory limit (512MB = 536870912 bytes) -mem_limit=$(echo "$inspect_json" | python3 -c "import sys,json; print(json.load(sys.stdin)[0]['HostConfig']['Memory'])") -if [ "$mem_limit" = "536870912" ]; then - pass "Memory=512m" -else - fail "Memory expected 536870912, got $mem_limit" -fi - -# SecurityOpt — must contain no-new-privileges -sec_opt=$(echo "$inspect_json" | python3 -c "import sys,json; opts=json.load(sys.stdin)[0]['HostConfig']['SecurityOpt'] or []; print(' '.join(opts))") -if echo "$sec_opt" | grep -q "no-new-privileges"; then - pass "SecurityOpt contains no-new-privileges" -else - fail "SecurityOpt missing no-new-privileges (got: $sec_opt)" -fi - -# No docker.sock bind mount -binds=$(echo "$inspect_json" | python3 -c "import sys,json; binds=json.load(sys.stdin)[0]['HostConfig']['Binds'] or []; print(' '.join(binds))") -if echo "$binds" | grep -q "docker.sock"; then - fail "docker.sock is bind-mounted" -else - pass "No docker.sock mount" -fi - -echo - -# --- runtime exec checks --- - -# touch /root/x should fail (read-only rootfs + unprivileged user) -if docker exec "$CONTAINER" touch /root/x 2>/dev/null; then - fail "touch /root/x succeeded (should fail)" -else - pass "touch /root/x correctly denied" -fi - -# /var/run/docker.sock must not exist -if docker exec "$CONTAINER" ls /var/run/docker.sock 2>/dev/null; then - fail "/var/run/docker.sock is accessible" -else - pass "/var/run/docker.sock not accessible" -fi - -# /etc/shadow should not be readable -if docker exec "$CONTAINER" cat /etc/shadow 2>/dev/null; then - fail "cat /etc/shadow succeeded (should fail)" -else - pass "cat /etc/shadow correctly denied" -fi - -echo -echo "=== Results: $PASS passed, $FAIL failed ===" - -if [ "$FAIL" -gt 0 ]; then - exit 1 -fi -exit 0