{"slug": "sandy-a-sandbox-for-ai-coding-agents-with-monitoring-and-policy-controls", "title": "Sandy – A sandbox for AI coding agents with monitoring and policy controls", "summary": "Kontext Security released Sandy 0.1.x, an experimental sandbox for AI coding agents that restricts agent access to a project without requiring a container or VM, and it has not completed an independent security audit. Sandy resolves all permissions before the agent starts, blocks self-granted access, and supports Claude Code, Codex, and OpenCode, with options for read/write directories, network blocking, and dry-run JSON output. The tool runs locally as a foreground command and can be installed via Homebrew, with optional integrations for Kontext and Numbat.", "body_md": "Warning\n\nSandy `0.1.x`\n\nis experimental and has not completed an independent security\naudit. See [Security and support](#security-and-support).\n\nRun AI coding agents in a sandbox.\n\nSandy gives an agent access to your project without giving it unrestricted access to your computer. The sandbox also applies to every command and tool the agent starts.\n\n```\nsandy run -- claude\n```\n\nThe goal is simple: running an agent through Sandy should feel like running it directly, except its access is explicitly limited.\n\nSandy does one job: sandbox processes. Credential brokering, behavioral monitoring, approvals, and audit logs remain separate tools that can be used alongside it.\n\nAll permissions are resolved before the agent starts. The agent cannot grant itself more access while it is running.\n\nIf Sandy cannot validate or apply the sandbox, the agent does not run. There is no fallback to unrestricted execution.\n\nSandy runs locally as a normal foreground command. It does not require a container, VM, background service, or modified copy of the agent.\n\n```\nbrew install kontext-security/tap/sandy\n```\n\nCheck that sandboxing works:\n\n```\nsandy doctor\n```\n\nSandy recognizes Claude Code, Codex, and OpenCode:\n\n```\nsandy run -- claude\nsandy run -- codex --sandbox danger-full-access\nsandy run -- opencode\n```\n\nCodex's internal sandbox cannot be nested reliably inside Sandy. The\n`danger-full-access`\n\nsetting makes Sandy the single sandbox and does not disable\nCodex's approval flow.\n\nOther commands work too:\n\n```\nsandy run -- cargo test\nsandy run -- python script.py\n```\n\nThe current project is read/write by default.\n\nGrant access to another directory:\n\n```\nsandy run --read ../shared-library -- claude\nsandy run --read-write ~/Downloads/output -- codex --sandbox danger-full-access\n```\n\nBlock network access:\n\n```\nsandy run --block-net -- cargo test\n```\n\nReview the resolved sandbox without starting the command:\n\n```\nsandy run --dry-run -- claude\n```\n\nDry-run output is a versioned JSON document. `dry_run_schema_version`\n\nidentifies\nits public schema independently from the internal launch-manifest protocol.\nOptional host integrations are reported in the canonical `runtime_controls`\n\narray, with one object per resolved runtime control containing `service`\n\n,\n`enabled`\n\n, and nullable `version`\n\nfields.\n\nAll Sandy options go before `--`\n\n. Everything after `--`\n\nis passed to the target\nunchanged.\n\nSandy uses built-in profiles to give supported agents access to the files they need while protecting sensitive configuration.\n\nKnown agents are detected from the command name. Everything else uses the generic profile. You can also select a profile explicitly:\n\n```\nsandy run --profile codex -- my-codex-wrapper\n```\n\nProfiles are versioned documents built into Sandy. They use Sandy's supported permissions and cannot contain raw sandbox rules.\n\nSandy resolves the command, paths, profile, environment, and permissions before launch.\n\nIt then starts a small bootstrap process that validates the launch, applies the sandbox, and replaces itself with the target command. The original Sandy process waits outside the sandbox and returns the target's exit status.\n\nThe target never runs before the sandbox is active. Every process it starts inherits the same restrictions.\n\nSandy does not store credentials, inspect behavior, approve tool calls, or keep an audit ledger.\n\nThose functions can be provided by separate tools. Sandy can preserve supported hooks and local services without making them part of its sandboxing core.\n\nCurrent optional integrations can be required explicitly:\n\n```\nsandy integrations setup kontext --agent claude\nsandy run --kontext -- claude\n\nsandy integrations setup numbat --agent codex\nsandy run --numbat -- codex --sandbox danger-full-access\n```\n\nFor known agent profiles, Sandy automatically preserves verified existing Kontext hooks and ownership-marked Numbat registrations whose complete generated shape it recognizes. The explicit flag makes that integration mandatory; without it, a missing integration has no effect on standalone sandboxing.\n\n`sandy integrations setup`\n\nis the explicit host-configuration path. It first\nchecks the selected agent's existing registration. A healthy integration is\nleft untouched; an installed provider is configured with its official setup\ncommand; and a missing provider is installed before configuration. Kontext is\ninstalled through its Homebrew tap and continues to own authentication, daemon\nsetup, and hook registration. For Kontext, `--agent`\n\nselects the registration\nSandy must verify; the provider-wide `kontext setup`\n\ncommand may configure\nother supported agents as well. Numbat uses a versioned Sandy-managed executable\nwhose public macOS release archive is bounded and verified against a SHA-256\ndigest embedded in Sandy before it is published. Sandy then invokes Numbat's\nofficial idempotent hook installer in file-output mode.\n\nThis command changes persistent host configuration and runs outside the\nsandbox. Ordinary `sandy run`\n\nand `sandy doctor`\n\nnever install, update, or\nrepair either provider. Existing installations on `PATH`\n\nare reused, and an\nalready active registration is authoritative even if its executable is not on\n`PATH`\n\n.\n\nNumbat hooks currently run inside the same sandbox as the agent. Sandy keeps\ntheir registration, executable, and rule directories readable but immutable,\nwhile the hook's record output and sequence-state database remain writable.\nDirect HTTP delivery from a Numbat hook is not supported; use file output. See\n[RUNTIME_CONTROLS.md](/kontext-security/sandy/blob/main/RUNTIME_CONTROLS.md) for the architecture, trust boundary,\nand deferred outside-sandbox decision model.\n\nHook discovery honors `CLAUDE_CONFIG_DIR`\n\n, `CODEX_HOME`\n\n,\n`OPENCODE_CONFIG_DIR`\n\n, and OpenCode's `XDG_CONFIG_HOME`\n\nfallback when those\nvariables name absolute configuration roots.\n\nAn operator can run Numbat's OTLP/HTTP collector outside Sandy and preserve only its default local-host port while all other networking is blocked:\n\n```\nnumbat collect --addr 127.0.0.1:4318\nsandy run --block-net --numbat-collector -- codex --sandbox danger-full-access\n```\n\n`--numbat-collector=PORT`\n\nselects a different nonzero port and requires\n`--block-net`\n\n. Sandy does not start or probe the collector and does not\nconfigure the agent's telemetry exporter. It authorizes TCP connect to the\nselected port on IPv4 addresses belonging to this Mac, including loopback and\nother local interfaces; it does not authorize external addresses or other\nports.\n\nSandy is a process sandbox, not a container or VM. It reduces what a process can access but does not provide a separate kernel, user account, or memory boundary.\n\nNetwork access is allowed by default and can be blocked with `--block-net`\n\n.\nKnown-agent profiles may grant access to agent state directories for\ncompatibility.\n\nSandy currently supports macOS. Version `0.1.x`\n\nis experimental, has not\ncompleted an independent security audit, and uses Apple's private, deprecated\nSeatbelt interface.\n\nRead [THREAT_MODEL.md](/kontext-security/sandy/blob/main/THREAT_MODEL.md) for the full security model and\n[SECURITY.md](/kontext-security/sandy/blob/main/SECURITY.md) for vulnerability reporting.\n\n```\nmake check\n```\n\nSee [AGENTS.md](/kontext-security/sandy/blob/main/AGENTS.md) and [CONTRIBUTING.md](/kontext-security/sandy/blob/main/CONTRIBUTING.md) before changing\nenforcement code.", "url": "https://wpnews.pro/news/sandy-a-sandbox-for-ai-coding-agents-with-monitoring-and-policy-controls", "canonical_source": "https://github.com/kontext-security/sandy", "published_at": "2026-08-27 16:33:44+00:00", "updated_at": "2026-08-27 16:49:44.971020+00:00", "lang": "en", "topics": ["ai-tools", "ai-safety", "developer-tools"], "entities": ["Kontext Security", "Sandy", "Claude Code", "Codex", "OpenCode", "Homebrew", "Kontext", "Numbat"], "alternates": {"html": "https://wpnews.pro/news/sandy-a-sandbox-for-ai-coding-agents-with-monitoring-and-policy-controls", "markdown": "https://wpnews.pro/news/sandy-a-sandbox-for-ai-coding-agents-with-monitoring-and-policy-controls.md", "text": "https://wpnews.pro/news/sandy-a-sandbox-for-ai-coding-agents-with-monitoring-and-policy-controls.txt", "jsonld": "https://wpnews.pro/news/sandy-a-sandbox-for-ai-coding-agents-with-monitoring-and-policy-controls.jsonld"}}