[[
wikihub
]]
Search
⌘K
Explore
People
For Agents
Sign in
Explore
People
For Agents
Sign in
@jacobcole / picortex — planning / docs/wiki/workspace-isolation.md
Suggest edit
Cancel
Submit suggestion
Title
Name
Note
--- visibility: public --- # Workspace isolation ## The question "When a compromised message in chat A tries to read chat B's files, what stops it?" ## The answer (v1) **POSIX permissions.** Chat A's processes run as a different Unix user (`chat-<hexA>`) from chat B's (`chat-<hexB>`). Chat B's home dir is `chmod 0700` and owned by `chat-<hexB>`. Chat A's user has no read access. ## What this buys us - Fast spin-up (< 1 s: `useradd`, `mkdir`, `chown`, `chmod`). - Tiny idle footprint (a tmux + bash — few MB). - Composes with cheap hardening (bubblewrap, Landlock, firejail) later. - Works on any Linux; no daemon. ## What this does NOT buy us - Kernel-level exploits cross boundaries. - Shared `/tmp`, shared `/dev`, shared networking by default. - Shared `/proc` can expose sibling-user process info (`ps aux`). - Resource limits need explicit cgroups. ## Minimum hardening (v1) 1. `chmod 0700` on home dirs, owned by the chat user 2. `pam_namespace` → per-user `/tmp` 3. `iptables` `owner match` → egress allowlist per UID 4. cgroups v2 → 256 MB RAM, 200 pids, quarter-CPU per chat 5. No sudo for chat users; no setuid binaries in their `PATH` 6. Restricted PATH: shims at `/usr/local/bin/picortex-shims` first, then nothing of consequence ## Known gaps (documented, not fixed in v1) - A chat user can `ps aux` and see other chat users' command lines. → Fix with `hidepid=2` mount option on `/proc`. - Shared DNS resolver config. → Fix with per-chat `resolv.conf` via namespaces. - Memory pressure from one chat can evict another (page cache). → Live with it. ## Stronger options (evaluated for D2) - **bubblewrap (`bwrap`)**: add to the tmux-entry wrapper; cheap, composable, solid defaults. - **Landlock (kernel ≥ 6.1)**: programmatic FS ACLs per-process; newer API, smaller ecosystem. - **nsjail**: more config knobs than bwrap; use if bwrap isn't granular enough. - **firejail**: friendliest defaults for interactive shells. - **gVisor**: overkill, kernel surface reduction but cost. - **Firecracker microVM per chat**: overkill but the strongest. D2 will rank these with Jacob's real threat model. Start simple; add layers empirically. ## Threat model (v1) | Threat | Likelihood | Impact | Controlled by | |---|---|---|---| | Prompt injection via a group member's message causes bot to exfil Jacob's DM files | high | high | per-chat user + `0700` | | Prompt injection causes bot to delete chat's own files | medium | low | acceptable — files are a cache | | Kernel exploit from chat user | low | high | keep kernel patched; consider bwrap/Landlock | | Bot accidentally posts a private file to the wrong chat | medium | high | sharing bridge R7 with BridgeEvent audit | | Someone gets Linq webhook secret | low | very high | HMAC + replay guard; rotate secret on suspicion | ## References - [Spec 001](../specs/001-workspace-isolation-linux-users.md) — concrete provisioning - [ADR-0002](../adrs/0002-linux-users-over-docker.md) — the Linux-users-not-Docker decision - `~/memory/research/openclaw-group-chat-security.md` — prior research on prompt-injection in group chats - D2 ticket — isolation-model comparison report