diff --git a/README.md b/README.md index 8e944f43..63a8ffcf 100644 --- a/README.md +++ b/README.md @@ -565,8 +565,10 @@ multiple sandboxes are running in parallel. **`sandcat/compose-agent.yml`** — the constant (non-user-editable) base for the agent service. `network_mode: "service:wg-client"` routes all traffic through -the WireGuard tunnel. The `mitmproxy-config` volume gives your container -access to the CA cert, env vars, and secret placeholders. +the WireGuard tunnel. The `mitmproxy-public` volume, mounted read-only at +`/mitmproxy-config/`, gives your container the CA cert, env vars, and secret +placeholders — the private `mitmproxy-config` volume, which also holds the CA +private key and the WireGuard keys, is never mounted into the agent. **`compose-all.yml`** — holds the user-customizable entries merged over that constant base. The agent-specific config bind-mounts (for example @@ -952,11 +954,11 @@ restart` after changing 1Password items. common logic via the `mitmproxy_addon_common.py` library. 2. On startup, the addon reads all available settings files (user, project, local), merges them according to the precedence rules above, and writes - `sandcat.env` to the `mitmproxy-config` shared volume - (`/home/mitmproxy/.mitmproxy/sandcat.env`). This file contains plain env vars + `sandcat.env` to the agent-facing `mitmproxy-public` shared volume + (`/mitmproxy-public/sandcat.env`). This file contains plain env vars (e.g. `export GIT_USER_NAME='Your Name'`) and secret placeholders (e.g. `export ANTHROPIC_API_KEY=SANDCAT_PLACEHOLDER_ANTHROPIC_API_KEY`). -3. App containers mount `mitmproxy-config` read-only at `/mitmproxy-config/`. +3. App containers mount `mitmproxy-public` read-only at `/mitmproxy-config/`. The shared entrypoint (`app-init.sh`) sources `sandcat.env` after installing the CA cert, so every process gets the env vars and placeholder values. 4. On each request, the addon first checks network access rules. If denied, the @@ -1081,7 +1083,7 @@ Cursor CLI support is available via `sandcat init --agent cursor`. `~/.config/sandcat/settings.json` (or project `.sandcat/settings.json`) using the same JSON shape as Cursor's global `cli-config.json` (permissions, model, network flags — not API keys). Sandcat merges settings layers at mitmproxy - startup, writes `/mitmproxy-config/cursor-cli-config.json`, and the agent + startup, writes `/mitmproxy-public/cursor-cli-config.json`, and the agent deep-merges that fragment into `cli-config.json` in agent-home on each start. Sandcat-owned keys win; other Cursor-written keys in that file (model choice, permissions allow/deny lists, etc.) are preserved. The Cursor user template @@ -1155,7 +1157,8 @@ from the host: ```mermaid flowchart TB subgraph volumes["Shared volumes"] - mc["mitmproxy-config
wireguard.conf
mitmproxy-ca-cert.pem
sandcat.env"] + mc["mitmproxy-config (private)
wireguard.conf
mitmproxy-ca.pem (CA private key)
dns.conf, extra_hosts"] + mp["mitmproxy-public (agent-facing)
mitmproxy-ca-cert.pem
sandcat.env"] ah["agent-home
/home/vscode
persists Claude Code state,
shell history across rebuilds"] end @@ -1166,23 +1169,31 @@ flowchart TB end mitm["mitmproxy"] -- "read-write" --> mc + mitm -- "read-write" --> mp wg["wg-client"] -- "read-only" --> mc - agent["agent"] -- "read-only" --> mc + agent["agent"] -- "read-only
at /mitmproxy-config/" --> mp agent -- "read-write" --> ah settings -. "bind-mount" .-> mitm projsettings -. "bind-mount" .-> mitm claude -. "bind-mount" .-> agent style mc fill:#f0e8fd,stroke:#904ad9 + style mp fill:#f0e8fd,stroke:#904ad9 style ah fill:#f0e8fd,stroke:#904ad9 style settings fill:#fde8e8,stroke:#d94a4a style projsettings fill:#fde8e8,stroke:#d94a4a style claude fill:#fde8e8,stroke:#d94a4a ``` -- **`mitmproxy-config`** is the key shared volume. Mitmproxy writes to it - (WireGuard keys, CA cert, `sandcat.env` with env vars and secret - placeholders); all other containers mount it read-only. +- **`mitmproxy-config`** is the private volume. Mitmproxy writes its WireGuard + keys and CA material there (including the CA **private** key), plus the + `dns.conf` and `extra_hosts` sidecars; only wg-client also mounts it, read-only. + The agent never gets it — see issue #25. +- **`mitmproxy-public`** is the agent-facing volume, holding only what the + sandbox legitimately needs: the CA **certificate** and `sandcat.env` (env vars + and secret placeholders). Mitmproxy writes it; the agent mounts it read-only + at `/mitmproxy-config/`, which is why paths inside the agent still start with + that prefix. - **`agent-home`** persists the vscode user's home directory across container rebuilds (Claude Code auth, shell history, git config). - **Settings files** are bind-mounted from the host into mitmproxy only — app @@ -1197,7 +1208,8 @@ flowchart TB ### Startup sequence The containers start in dependency order. Each step writes data to the shared -`mitmproxy-config` volume that the next step reads: +volumes that the next step reads — `mitmproxy-config` for wg-client, and +`mitmproxy-public` for the agent: ```mermaid sequenceDiagram