Skip to content

Security Model

Doable's security posture is built on defense in depth. The same dangerous capability β€” running AI-generated code on your server β€” is wrapped by five independent layers, any one of which would block a typical attack.

Trust boundaries

                       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   PUBLIC INTERNET ──▢│ nginx / Caddy   (TLS, rate-limit)β”‚
                       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                         β”‚
                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                  β”‚      127.0.0.1 only β€” TRUSTED HOST          β”‚
                  β”‚                                              β”‚
                  β”‚   β”Œβ”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”              β”‚
                  β”‚   β”‚ web β”‚    β”‚ api β”‚    β”‚ ws  β”‚  app procs   β”‚
                  β”‚   β””β”€β”€β”¬β”€β”€β”˜    β””β”€β”€β”¬β”€β”€β”˜    β””β”€β”€β”¬β”€β”€β”˜              β”‚
                  β”‚      β”‚          β”‚          β”‚                  β”‚
                  β”‚      β”‚     β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”     β”‚                  β”‚
                  β”‚      β”‚     β”‚postgres β”‚     β”‚                  β”‚
                  β”‚      β”‚     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚                  β”‚
                  β”‚      β”‚                                         β”‚
                  β”‚      β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”            β”‚
                  β”‚      └──▢│ docore worker process  β”‚            β”‚
                  β”‚          β”‚  (sandbox + isolator)  β”‚            β”‚
                  β”‚          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜            β”‚
                  β”‚                     β”‚                          β”‚
                  β”‚            β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”                β”‚
                  β”‚            β”‚ dovault jail     β”‚  per-project   β”‚
                  β”‚            β”‚  (FS + cgroups)  β”‚                β”‚
                  β”‚            β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                β”‚
                  β”‚                     β”‚                          β”‚
                  β”‚            β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”                β”‚
                  β”‚            β”‚ project files +  β”‚                β”‚
                  β”‚            β”‚  Vite dev server β”‚                β”‚
                  β”‚            β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                β”‚
                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The five layers

# Layer What it protects against
1 TLS proxy (nginx/Caddy) Eavesdropping, DDoS at L7, basic abuse
2 JWT auth + role checks Unauthorized access to API endpoints
3 Tool/policy sandbox (docore) The AI calling tools it shouldn't (rm -rf, fetch from attacker URL)
4 Process isolation (docore isolator) A compromised AI worker affecting other workers / the API process
5 Runtime jail (dovault) Spawned project processes (Vite, npm scripts) escaping their project root or starving the host

Each layer assumes the previous one might fail. That's the point.

Specific threats and how they're addressed

"The AI deletes /etc/passwd"

  • Policy denies rm outright via DEFAULT_DANGEROUS_COMMANDS.
  • Sandbox rejects the call before execution, even if the model produces it.
  • dovault jail rejects writes outside the project root at the OS level.

"The AI exfiltrates code to an attacker's URL"

  • URL allow-list in policy (DEFAULT_URL_ALLOWLIST) blocks fetches outside known package registries / docs sites.
  • Audit log records every attempted fetch β€” admins see them.

"Generated code includes a malicious npm package"

  • pnpm install runs inside the dovault jail with no network access beyond the registry allow-list.
  • postinstall scripts execute with the same Node permission model β€” they can't read outside the project, can't fork unrelated processes, can't exhaust memory.

"A user runs an infinite loop in their Vite dev server"

  • Resource limits (cgroups on Linux, Job Object on Windows) cap each project at e.g. 150 MB / 30% CPU.
  • The OS kills the process when limits are exceeded; the host stays healthy.

"Stolen JWT"

  • Short access-token TTL (default 15 minutes).
  • Refresh tokens in HttpOnly cookies (immune to XSS).
  • Stateless tokens β€” rotating JWT_SECRET invalidates everything at once.

"Compromised OAuth/integration token"

  • Stored encrypted with ENCRYPTION_KEY (AES-256-GCM).
  • Per-tool revocation from the audit panel.
  • Rotating ENCRYPTION_KEY invalidates all stored tokens.

"Cross-tenant data leak"

  • Every query in packages/db/src/queries/ is scoped by workspace ID.
  • Middleware enforces workspace membership before route handlers run.
  • Project filesystems live in distinct directories under PROJECTS_ROOT/; the jail prevents traversal.

Things Doable does NOT do

  • No automatic dependency vulnerability scanning β€” bring your own (Snyk, Dependabot).
  • No automatic AI prompt-injection defense beyond the sandbox layers β€” adversarial users can craft prompts that try to trick the agent into denied behavior. The sandbox catches the resulting tool calls; the model itself isn't hardened.
  • No outbound egress firewall by default β€” if you accept untrusted user projects, run the host on a network with default-deny egress.

See also