Skip to content

Explore purpose-built sandbox tooling for MCP-server (and exec) subprocesses #375

Description

@mlieberman85

Context

Feature 031 (mcp handler for external MCP servers) ships with a curated env-inheritance safe-set (PATH, HOME, LANG, LC_, SSL_CERT_FILE, XDG_) plus the operator's TOML env block. Everything else from darnit's parent shell is dropped before the child MCP server subprocess is spawned. That's a real first line of defense against operator-shell credentials leaking to an arbitrary MCP server, but env-curation alone is a weak sandbox: the child still shares the filesystem, network, process namespace, and syscall surface with darnit.

The same weakness applies to the existing exec handler, which today inherits the full parent env and has zero isolation guarantees.

This issue is to survey purpose-built sandbox tooling and decide which (if any) to require or optionally support for darnit-spawned subprocesses.

Non-goal

Darnit is not writing its own sandbox. The scope here is "which external tool(s) do we integrate with and under what conditions."

Candidates to evaluate

  • nono.sh (flagged by @mlieberman85 as a starting point).
  • bubblewrap (bwrap): user-namespace sandbox, widely available on Linux, used by Flatpak and Firefox. Rootless.
  • nsjail: Google's process-isolation tool. Sits above bwrap.
  • firejail: user-friendly SUID sandbox; adoption/security posture worth reviewing.
  • gVisor (runsc): kernel-syscall interposition. Heavier; targeted at containers rather than one-shot subprocesses.
  • Landlock (kernel API, Linux 5.13+): capability restriction from inside the process, no external tool needed. Requires darnit to invoke landlock syscalls before exec.
  • seccomp-bpf (kernel API): syscall filtering. Same shape as Landlock.
  • macOS sandbox-exec and Windows job objects for cross-platform parity.

Framing questions

  1. What isolation properties does darnit actually need? At minimum: filesystem read-only outside a small allowlist; no writes outside a tempdir; no network unless the server declares it; no access to ~/.aws, ~/.docker, ~/.ssh, ~/.claude, ~/.gnupg, ~/.netrc, ~/.kube, and similar credential-bearing paths.
  2. Which sandbox tools cover which platforms (Linux, macOS, Windows, containers on CI)? What's the "not on this platform" degradation story?
  3. Should darnit REQUIRE a sandbox (opt-out) or OFFER one (opt-in)? Constitution II leans toward "require": a compliance tool that silently reduces its own trust guarantees when the sandbox is unavailable is bad. Constitution III leans toward "TOML expresses the requirement", i.e., per-server sandbox = "bwrap" in [mcp_servers.<name>].
  4. What's the story for CI runners where the sandbox tool isn't available? INCONCLUSIVE with an install hint, matching feature 031's binary-absent behavior.
  5. Does the same mechanism apply to the exec handler? Yes, probably -- but that's a much larger blast radius (many controls use exec today), so it may need a phased rollout.

Prerequisites

  • Feature 031 (mcp handler) merged: this issue extends its trust story.
  • No expectation on any specific outcome. This is an evaluation issue; the output is a design note, not code.

Related

  • Feature 031 spec: specs/031-mcp-server-handler/spec.md (specifically the 2026-08-16 Q1 clarification on env inheritance and the follow-up sandbox note in Assumptions).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions