Skip to content

Sandboxing User Projects

Same content as the architecture page but written from a security standpoint. The deep dive lives at:

Five sandbox layers

  1. Policy layer — allow-list of tools, MCP servers, shell commands, URLs.
  2. Permission handler sandbox — gates each tool call against the policy, with audit.
  3. Process isolator — spawns each AI session's worker in a separate OS process (nsjail / systemd / Job Object).
  4. dovault jail — Node Permission Model + cgroups around any spawned project process (Vite, npm).
  5. OS containment — non-root user, 127.0.0.1 binding, UFW firewall, optional Docker isolation.

Threat → mitigation map

Threat Mitigation
AI deletes critical files Policy denies rm; jail rejects writes outside project root
AI exfiltrates source via fetch URL allow-list in policy; audit log
AI runs CPU/memory bomb Resource limits (cgroups / Job Object) kill the process
Malicious npm postinstall script dovault confines npm install to project root with no extra permissions
AI worker crash takes down the API Worker runs in a separate process; engine restarts it
One workspace's project reads another's Each project has its own jail rooted at its own directory; queries are workspace-scoped
Compromised AI provider sends a malicious payload Provider responses are parsed safely; tool calls still go through the sandbox

Tuning the sandbox

For internal-only deployments where every user is trusted, you can relax the policy in Workspace Settings → AI → Tools:

  • Add commands to the safe list.
  • Widen the URL allow-list.
  • Allow child_process and worker_threads in dovault.

For multi-tenant SaaS deployments where users are anonymous internet strangers, tighten instead — see the Hardening Checklist.

What the sandbox does NOT cover

  • Quota abuse — a determined user can still burn your AI credits. Set per-workspace credit caps.
  • Native Node addons — can bypass the Permission Model. Block them in dovault.permissions if you accept untrusted projects.
  • Browser-side attacks in the published sites — Doable doesn't sandbox what your users put in their own HTML/JS at runtime. That's their app's responsibility.

Audit log

Every tool call (allow, deny, error) is recorded:

  • In memory with the session.
  • In the activity_events table.
  • Visible at Workspace Settings → Audit.

For SIEM integration, tail the activity_events table or pipe journalctl -u doable -f | grep '\[audit\]'.

See also