Skip to content

Sandboxing & Security

Suitcase is a local-first agent. It runs in Docker, connects to your LLM, and stores everything locally.

Security Audit

Before remote exposure or after changing channel config, run the security audit:

bash
./scripts/security_audit.sh             # baseline audit
./scripts/security_audit.sh --deep      # deep scan (secrets, images, webhooks)
./scripts/security_audit.sh --fix       # auto-fix permissions
./scripts/security_audit.sh --deep --fix  # full audit + auto-fix
./scripts/security_audit.sh --json      # JSON output for machines

The audit checks:

CategoryChecks
NetworkPort binding (loopback vs 0.0.0.0)
DockerSocket mount, runtime sandbox, running containers
ChannelsDiscord/Telegram DM policies, allowlists, pairing
SecretsLLM API key presence, .env permissions, GitHub token type
ToolsWrite confinement, risky power combinations
InstallRoot user, Docker Compose version, volume permissions

Deep mode (--deep) adds:

  • Secret scanning of suitcase_world/ files for leaked tokens
  • Docker image inspection
  • Env file permissions (comprehensive)
  • Channel webhook verification
  • Running container and volume inspection

Fix mode (--fix) auto-remediates:

  • .env permissions → 600
  • suitcase_world/ permissions → 700
  • suitcase_world/secrets/ permissions → 700, *.json → 600
  • Disables risky channel powers (Discord, Telegram)

Also available as an API: GET /api/security/audit?deep=true&fix=true

Local-First Boundary

  • The FastAPI app serves the web UI on localhost:8000.
  • The SQLite database is stored in the suitcase-data Docker volume.
  • Agent memory and generated artifacts live in suitcase-world and suitcase-logs volumes.
  • LLM credentials are stored server-side and never returned to the browser after save.

Write Confinement

All writes must resolve inside suitcase_world/. The path guard blocks:

  • Absolute paths outside the world root
  • Parent directory traversal with ..
  • Symlink escapes

This keeps reflections, reports, and career artifacts in isolated, reviewable storage.

Secrets

Secrets stay server-side:

  • LLM API keys are saved via the Setup UI and stored in Docker secrets.
  • The setup API reports whether a key exists, not the key value.
  • Powers requiring tokens (Discord, Telegram, Brave, GitHub, Restic) accept values through inline password fields — values are never returned to the browser.
  • Logs and diagnostics avoid printing secret values.

If you accidentally paste a token into a world file or chat message, rotate that token.

Command Logger

When the Command Logger power is enabled, every tool call is logged to suitcase_world/logs/commands.log (JSONL). Secret-bearing input fields are redacted.

Model Choice Matters

The LLM is part of the security boundary because it must follow Suitcase's system prompt, world rules, and tool instructions.

  • Cloud models (OpenAI, Anthropic) are the recommended default for safety and instruction-following reliability.
  • Local models can be used via the compatible modes. Models below 8B parameters may struggle with prompt injection resistance. Gemma 4 26B MoE is a verified local baseline.

Integrations

  • Discord: Bot token stored server-side. Messages are treated as untrusted input.
  • Telegram: Bot token stored server-side. Allowed user IDs restrict access.
  • GitHub: Token stored in .env or via Setup UI. Used for repo evidence sync.
  • Brave Search: API key stored via Setup UI. Rate-limited to 1 request/second via SKILL.md guidance.
  • Phone Location: Webhook secret stored via Setup UI. Accepts location data from OwnTracks/GPSLogger.

What To Review

Review these before trusting a new setup:

  1. suitcase_world/WORLD.md for world rules and safety boundaries
  2. suitcase_world/SOUL.md for voice and trust principles
  3. .env for local configuration and secrets
  4. The setup dashboard to verify which powers are enabled

For the broader architecture, see Architecture.

Your private career copilot.