3.2 KiB
Security
One line: the bot runs on your own machine; your data does not leave by default — only the model API calls you choose, and (if you sign in to an account) the ciphertext of your backup.
Reporting: open a private security advisory on the repo (Gitea › Security) or write the owner. We aim to answer in 3 business days, fix in 90. No public disclosure of unfixed issues.
Trust boundaries
- Your computer — the bot's brain, hands,
state.json, vault. Your OS account is the boundary; shell commands run in the macOS sandbox (denies~/.aws, Keychain, AnyBot's own data). - The bot's cloud box — a Docker container the bot roots; automatically switched to gVisor (
runsc) when the host has it: the kernel joins the boundary. - Docker API — no
docker.sock: a docker-socket-proxy whitelist (containers/images/networks subset; noexec, noprivileged). - Relay — stores hashes only: argon2id passwords, hashed tokens/sessions; your backup arrives sealed with a key derived from your password (PBKDF2-HMAC-SHA256 120k → AES-256-GCM). The relay never sees plaintext, and it is self-hosted.
- Model providers — see the chats and screenshots you hand them, never your files, vault secrets, or keys.
Where secrets live
| Thing | Where | What an attacker gets |
|---|---|---|
| Model API keys | state.json (0600) |
that provider's bill — disk encryption, provider 2FA |
| Vault (logins/cards) | vault.bin: AES-256-GCM, key in the system keychain (0600 file fallback) |
nothing without the keychain; the model never sees secrets — lists come blanked, every fill is approved per use |
| Account password | your app; relay keeps only argon2id (m=19MiB, t=2) | hashes; the backup stays sealed behind your password |
| 2FA | TOTP secret + 8 hashed recovery codes on the relay | disabling 2FA needs password + code in the same turn |
| Sessions | hashed rows; logout-everywhere | a stolen session file works until logout (relay is a trust point) |
Prompt-injection defenses (layers, not walls)
- Outside content is wrapped as
<untrusted>— data, never orders. - Sensitive clicks (send/pay/transfer/…): asked every time, direct mode included — no grant silences it; the gate is in the harness, not the prompt.
- First use of every app/computer needs your approval (policy at the data layer).
- Card numbers and OTPs in screenshots are painted black before the model sees them.
- Every turn's actions land in an auditable oplog → SQLite audit (30 days), with a phone timeline.
Honest limit: injection has no absolute defense — which is why the last line is a human at the approval gate. The model never issues its own passes.
Network surface
Loopback by default; egress binds loopback plus detected Docker bridge gateways, never 0.0.0.0. The phone talks to your relay over Caddy HTTPS. LAN mode is opt-in and password-gated.
Known limits
Same OS user = same trust; providers see chats/screenshots you send them; gVisor is optional on your box; backup security is bounded by your password; a breached relay leaks hashes and ciphertext, not plaintext.
Hardening
Disk encryption, capped + 2FA'd provider keys, HTTPS-only relay with 2FA, gVisor on the box host, per-app "ask always" on your sensitive apps.