Shell sandbox

The shell sandbox runs each command the agent starts inside your operating system’s own sandbox. A sandboxed command can write only where you allow, cannot see your credential folders, and reaches the network only for hosts you approve. It is a second fence behind permission rules: even a command you approved cannot wander off.

SystemSandbox used
macOSSeatbelt (sandbox-exec, built into the system)
Linuxbubblewrap (bwrap, from your distribution’s packages)
WindowsNot available

The sandbox is off until you turn it on. It applies to commands the agent runs through the Bash tool. Hooks and MCP servers are started without it.

Turn it on

HowLasts
/sandbox on · /sandbox offThis session
/sandbox network on · /sandbox network offThis session
SYNTIC_BASH_SANDBOX=1Every run with that variable
"sandbox": { "enabled": true } in settingsEvery session that reads the file

/sandbox with no arguments shows the current state: on or off, which sandbox program, network access, writable folders and excluded commands. A /sandbox choice beats the environment variable, which beats the settings file.

Check that it works

Turn it on, then ask the agent to run something that should fail:

> /sandbox on
> run: touch ~/sandbox-test && echo created

The write outside the working folder is refused by the operating system, and the agent sees the error. A command inside your project still works as normal.

What a sandboxed command may do

AreaDefault
WriteThe working folder and the per-user temp folder, plus folders you add. With strictCwd, only the working folder and added folders.
ReadThe whole system, except credential folders and anything you deny.
NetworkOff, unless you allow hosts or switch it on (see Network rules).
Git internalsA repository’s .git/hooks and git config can be read but never written, so a command cannot plant a hook. A linked worktree may still write its shared git folder, so commits work.
CredentialsHidden even when a readable folder covers them (see below).

Credentials stay hidden

When a command runs in the sandbox, these folders and files in your home folder are masked, even if you run in your home folder or allow reads of ~:

.ssh, .gnupg, the credential folders of cloud command-line tools, .kube, .docker/config.json, .netrc, .npmrc, .pypirc, .git-credentials, .config/gh/hosts.yml, and Syntic’s own .syntic folder.

Secret-looking environment variables are removed too. That covers well-known names such as cloud access keys and database passwords, and any variable whose name ends in TOKEN, SECRET, PASSWORD, PASSWD, PAT, APIKEY, API_KEY, ACCESS_KEY, SECRET_KEY, PRIVATE_KEY or AUTH_TOKEN. Values you set for the session with /env are passed through on purpose. Syntic Code’s own sign-in is never passed to any command, sandboxed or not.

Settings

{
  "sandbox": {
    "enabled": true,
    "autoAllowBashIfSandboxed": true,
    "network": {
      "allowedDomains": ["github.com", "*.npmjs.org"],
      "deniedDomains": ["paste.example"]
    },
    "filesystem": {
      "allowWrite": ["~/.cache/build"],
      "denyWrite": ["./secrets"],
      "denyRead": ["~/private/**"]
    },
    "excludedCommands": ["docker *"]
  }
}
KeyEffect
enabledTurn the sandbox on.
failIfUnavailableRefuse commands when the sandbox program cannot run, instead of running them unsandboxed with a warning.
autoAllowBashIfSandboxedA command that will really run sandboxed needs no prompt. Deny rules, ask rules and the safety checks still apply.
strictCwdOnly the working folder (and added folders) is writable; the temp folder is not.
network.allowedDomainsHosts commands may reach: example.com exactly, *.example.com for its subdomains, * for anything.
network.deniedDomainsHosts that are always refused, even with *.
network.allowManagedDomainsOnlyPolicy: only hosts from managed settings count; users’ own entries are ignored.
filesystem.allowWriteExtra writable folders. ~/x is under your home folder; a relative path is under the working folder.
filesystem.denyWriteFolders that are never writable (they can still be read).
filesystem.allowReadExtra readable folders.
filesystem.denyReadFolders that can be neither read nor written. Glob patterns work.
filesystem.allowManagedReadPathsOnlyPolicy: only read paths from managed settings count.
excludedCommandsCommands that always run outside the sandbox, such as docker * or bazel:*.
allowUnsandboxedCommandsLet a single call ask to run outside the sandbox. Off by default.
allowAppleEventsmacOS: let sandboxed commands control other apps (for example through osascript). Off by default.
bwrapPathLinux: the absolute path of the bwrap program to use instead of the one on your PATH. User and policy settings only.
extraDirsOlder spelling of filesystem.allowWrite; both are honored.

How files combine

Settings from every file are merged, with stronger files winning for single values. The deny lists (deniedDomains, denyWrite, denyRead) are different: entries from every file add up, so no file can remove another file’s deny entry.

A repository’s own settings can only make the sandbox stricter. From .syntic/settings.json or .syntic/settings.local.json, only these are read: enabled, strictCwd and failIfUnavailable when set to true, and the three deny lists. A project cannot allow hosts, add writable folders, exclude commands, permit unsandboxed runs or change bwrapPath.

Network rules

The operating system can only switch networking fully on or off for a process; it cannot filter by host. So Syntic Code looks at each command and decides before it starts:

  1. If the command uses a denied host, it is refused before it runs, and you are told which entry matched. This beats every way of turning the network on.
  2. If every host the command uses is allowed (or allowedDomains holds *), it gets the network.
  3. Otherwise it runs with the network off. If it then fails, the agent gets a note that a host was not on the list.

Hosts are found in:

  • URLs (https://host/...), user@host:path remotes, and host arguments to network tools such as curl, wget, ssh, scp and nc;
  • the default registry of a package manager the command clearly uses: npm, pnpm and yarn; pip, uv and poetry; cargo; gem and bundle; go; brew. A --registry or --index-url on the command replaces the default;
  • git remotes: git clone, fetch, pull, push and ls-remote without a URL use the remote’s address from .git/config.

A command that names no host it can see gets the network only when allowedDomains holds *.

⚠️

Hosts a program chooses by itself are not seen: a script that downloads from an address in a file, a proxy or mirror set in a config file, or an image registry chosen by a container tool. Such commands get the network only with *, and then the deny list cannot stop them. Treat host rules as a guard against the commands you can read, not a firewall.

/sandbox network on and SYNTIC_BASH_SANDBOX_NET=1 switch the network on for every sandboxed command, except those that name a denied host.

Running a command outside the sandbox

Some tools do not work in a sandbox: container engines, tools that talk to system services, or builds that write to many places. You have two ways out:

  • excludedCommands: list commands that should always run normally. They still go through the usual permission prompt.
  • allowUnsandboxedCommands: lets the agent mark one call as needing to run outside. Without this setting (or SYNTIC_BASH_ALLOW_UNSANDBOXED=1), such a request is ignored and the command stays sandboxed, so the model can never turn the fence off by itself.

How the sandbox relates to permissions

The sandbox and permission rules work at different moments. Rules decide whether a command runs; the sandbox limits what it can touch once it does.

SettingEffect
Deny and ask rulesAlways apply first, sandbox or not.
autoAllowBashIfSandboxedSkips the prompt only for commands that will truly run sandboxed. An excluded command, or one marked to run outside, still asks.
Permission modesUnchanged. In auto mode, the checks for high-impact actions still apply.
Read and Edit deny rulesGovern the agent’s file tools. Use sandbox.filesystem.denyRead to keep shell commands away from the same files.

For organizations

Put the sandbox block in managed settings to set it for everyone. Two policy-only switches stop users from widening it:

{
  "sandbox": {
    "enabled": true,
    "failIfUnavailable": true,
    "network": { "allowedDomains": ["github.example.com", "registry.npmjs.org"], "allowManagedDomainsOnly": true },
    "filesystem": { "allowRead": ["/opt/tools"], "allowManagedReadPathsOnly": true }
  }
}

With allowManagedDomainsOnly, users’ allowedDomains entries are ignored and only the policy’s count. allowManagedReadPathsOnly does the same for allowRead. Deny lists from users and projects still add up on top.

Environment variables

VariableEffect
SYNTIC_BASH_SANDBOX1, true, yes or on turns the sandbox on; any other value turns it off.
SYNTIC_BASH_SANDBOX_NETAllow or block the network for every sandboxed command.
SYNTIC_BASH_SANDBOX_EXCLUDEDExcluded commands, separated by commas or new lines. Replaces excludedCommands.
SYNTIC_BASH_ALLOW_UNSANDBOXEDSame as allowUnsandboxedCommands.

Want a different fence for everything? SYNTIC_SHELL_PREFIX puts your own isolation tool in front of every command, for example firejail --net=none.

Troubleshooting

ProblemWhat to check
A warning says the sandbox program was not found, and commands run unsandboxedOn Linux, install bubblewrap or set bwrapPath. On Windows the sandbox is not available. Set failIfUnavailable to refuse instead.
A command is refused for a denied hostA deniedDomains entry in some settings file matched. Deny entries add up across files; run syntic doctor or check your organization’s policy.
A download or install fails offlineThe host is not on allowedDomains. Add it, or use /sandbox network on for this session.
A build cannot write its cacheAdd the cache folder to filesystem.allowWrite, or check whether strictCwd is on.
A container command failsAdd it to excludedCommands, for example docker *.
git push over SSH failsSSH keys are hidden in the sandbox by design. Push from your own terminal, or exclude the command.
A tool that drives other macOS apps failsSet allowAppleEvents in your user settings.
A project’s sandbox settings seem ignoredProjects can only tighten the sandbox. Allowing hosts or folders must come from your user settings or policy.