From 180abbab3945766c7e7bc0b791042996887a60cc Mon Sep 17 00:00:00 2001 From: Sam & Claude Date: Tue, 23 Jun 2026 15:24:37 +0200 Subject: [PATCH] =?UTF-8?q?docs:=20security=20baseline=20=E2=80=94=20live?= =?UTF-8?q?=20USB=20boot=20checklist?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cross-reference from OSA audit (2026-06-23): SSH hardening, MCP socket, firewall, listening ports, service accounts, external MCP servers. Each check has command + expected output. OSA exceptions documented: password auth kept for dev access. USB should be stricter — key-only SSH, no 0.0.0.0 bindings. Skill saved: security-audit-clawdie (freebsd category) --- docs/SECURITY-BASELINE.md | 89 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 docs/SECURITY-BASELINE.md diff --git a/docs/SECURITY-BASELINE.md b/docs/SECURITY-BASELINE.md new file mode 100644 index 00000000..879078be --- /dev/null +++ b/docs/SECURITY-BASELINE.md @@ -0,0 +1,89 @@ +# Security Baseline — Live USB Boot Checklist + +2026-06-23 | OSA audit → live USB alignment + +Cross-reference of security checks that should pass on every booted +Clawdie USB. Derived from the OSA security audit on 2026-06-23. + +## Boot-time checks + +### SSH hardening + +| Check | Command | Expected | +|---|---|---| +| Password auth disabled | `grep PasswordAuth /etc/ssh/sshd_config` | `PasswordAuthentication no` | +| Root login disabled | `grep PermitRoot /etc/ssh/sshd_config` | `PermitRootLogin no` | +| Key-only auth | `grep PubkeyAuth /etc/ssh/sshd_config` | `PubkeyAuthentication yes` | + +### Service accounts + +| Check | Command | Expected | +|---|---|---| +| colibri user exists | `pw usershow colibri` | uid 3002, shell `/usr/sbin/nologin` or `/bin/sh` with restrict | +| colibri password locked | `pw usershow colibri \| grep '*'` | `*` (asterisk = locked) | +| colibri in clawdie group | `id colibri` | includes `clawdie` group | +| SSH key restricted | `cat /var/db/colibri/.ssh/authorized_keys` | `command="colibri-mcp-ssh",restrict,no-pty,...` | +| Home dir owned by colibri | `ls -la /var/db/colibri/` | `colibri:colibri` on the directory itself | + +### MCP socket + +| Check | Command | Expected | +|---|---|---| +| Socket exists | `ls /var/run/colibri/colibri.sock` | exists | +| Restricted to clawdie group | `ls -la /var/run/colibri/colibri.sock` | `srwxrwx--- clawdie:clawdie` | + +### Firewall (pf) + +| Check | Command | Expected | +|---|---|---| +| Default deny | `sudo pfctl -sr` | `block drop all` as final rule | +| Only http/https public | `sudo pfctl -sr \| grep vtnet0` | only ports 80, 443 (and optionally 22) | +| SSH Tailscale-only (optional) | `sudo pfctl -sr \| grep ssh` | no vtnet0 ssh rule, only tailscale0 | + +### Listening ports + +| Check | Command | Expected | +|---|---|---| +| No unexpected listeners | `sudo sockstat -l` | nginx (80/443), colibri (socket), sshd | +| Dashboard Tailscale-only | `sudo sockstat -l \| grep 9119` | Hermes dashboard — should be on localhost or tailscale0 | +| No 0.0.0.0 bindings | `sudo sockstat -l \| grep '*'` | only nginx 80/443 (public web), nothing else | + +### MCP access test + +| Check | Command | Expected | +|---|---|---| +| Local MCP works | `colibri-mcp tools` | lists tools | +| SSH MCP from colibri user | `ssh -i mother-mcp colibri@localhost 'tools'` | lists tools (single-word invocation only) | +| colibri_external_mcp_servers | via MCP tool | shows registered external servers | + +### External MCP servers + +| Check | Command | Expected | +|---|---|---| +| Config exists | `cat /usr/local/etc/colibri/external-mcp.json` | valid JSON with servers | +| COLIBRI_MCP_EXTERNAL_CALL | `grep EXTERNAL_CALL /usr/local/etc/colibri/provider.env` | `COLIBRI_MCP_EXTERNAL_CALL=1` | +| geodesic-dome-mcp installed | `ls /usr/local/bin/geodesic-dome-mcp` | exists, executable | +| build-colibri.sh installed | `ls /usr/local/bin/build-colibri.sh` | exists, executable | +| colibri-mcp-ssh wrapper | `ls /usr/local/bin/colibri-mcp-ssh` | exists, executable | + +## OSA-specific exceptions (production) + +| Exception | Reason | +|---|---| +| Password auth enabled on vtnet0 | User preference for OSA access during development | +| SSH port 22 on public interface | OSA is the mother node, needs public SSH for now | +| Port 9119 on 0.0.0.0 | Hermes dashboard, pf-limited to Tailscale on vtnet0 | + +These exceptions should NOT be present on a booted USB — the USB is a +single-user operator station, not a public server. + +## Tests performed on OSA (2026-06-23) + +- ✅ SSH MCP from colibri user: `ssh -i mother-mcp colibri@localhost 'tools'` — works +- ✅ Home dir ownership fixed: `chown colibri:colibri /var/db/colibri` +- ✅ MCP socket permissions: `srwxrwx--- clawdie:clawdie` +- ✅ pf firewall: default deny, only http/https/ssh on vtnet0 +- ✅ colibri authorized_keys: restrict + no-pty + forced command +- ✅ COLIBRI_MCP_EXTERNAL_CALL=1 in provider.env +- ✅ external-mcp.json: mother-build + geodesic-dome registered +- ⚠️ Port 9119 (Hermes dashboard) bound to 0.0.0.0 — pf limits to Tailscale -- 2.45.3