deniz.in

Markets

Weather

Loading weather

· via dev.to (home feed)

Solon's Java port of Claude Code's sandbox jails AI agent commands at the OS level

A dev.to walkthrough introduces solon-ai-sandbox, a Java port of Claude Code's sandbox-runtime that wraps agent commands in OS-enforced filesystem and network isolation on macOS, Linux and Windows.

Solon's Java port of Claude Code's sandbox jails AI agent commands at the OS level

A sandbox the operating system enforces

A walkthrough on dev.to from the Solon Java project introduces solon-ai-sandbox, a module that wraps commands issued by AI coding agents in genuine filesystem and network isolation. According to the post, it is a Java port of Claude Code's sandbox-runtime and works across macOS, Linux and Windows.

The premise is blunt: prompt-level instructions, such as asking an agent not to read sensitive files, are requests to a stochastic process rather than a security boundary. Once an agent can execute shell commands on a machine, the only restrictions that reliably hold are the ones the operating system itself imposes.

Native isolation instead of containers

Containers remain the sensible answer for server-side agents, the post concedes, but the agents people run interactively — the ones editing a working copy of a repository — usually sit on a laptop with no container around them. Booting a VM or container for every command is too slow for that workflow, and it cuts the agent off from the working tree it is supposed to edit.

solon-ai-sandbox aims for the middle ground: keep the agent inside the project directory, let it reach the registries and package mirrors a build requires, and block everything else without a container runtime in the picture. Each platform uses its native facility — sandbox-exec with a generated Seatbelt profile on macOS, bubblewrap plus socat on Linux, and srt-win.exe with a Windows Filtering Platform layer on Windows. The module's only dependency is solon-ai-core.

Wrapping a command

The API centres on SandboxManager, a final class of static methods with one sandbox per process. After initialising it with a runtime configuration and an optional interactive callback, a single call — wrapWithSandbox — turns a command like git status into a wrapped shell string to hand to bash. On macOS that produces a sandbox-exec invocation; on Linux, a bubblewrap invocation with the appropriate bind mounts and namespaces. Application code never branches on the platform.

Asymmetric filesystem rules

Filesystem policy deliberately treats reads and writes differently. Writes are allow-only: everything is denied by default, permitted paths are listed explicitly, and denyWrite carves exceptions back out of that list. The manager automatically grants the paths a process genuinely needs, such as /dev and temp directories, and an empty write allowlist is the strictest possible setting.

Reads invert the logic and start open, because blocking reads machine-wide would break compilers, the JVM and much of userspace. Instead, denyRead marks protected regions — the post's example blocks ~/.ssh and ~/.aws — and allowRead can re-open specific paths inside them.

The author also advises denying writes into .git, since a tampered Git directory works well as a persistence mechanism, and notes that access to .git/config sits behind its own allowGitConfig flag, disabled by default.

Network control through a proxy

Network isolation is implemented as a local HTTP and SOCKS5 forward proxy. The sandboxed process is pointed at it through environment variables, and every request is checked against allowlists and denylists that support wildcard patterns such as *.github.com. A utility called HostUtils normalises IPv4, IPv6 and hostname forms, so matching cannot be sidestepped by writing an address a different way.

The proxy design buys live updates: SandboxManager.updateConfig takes effect on the next request, including for agent processes that are already running. Filesystem rules are not hot in the same way — on macOS they are compiled into the Seatbelt profile when a command is wrapped, and on Windows they must be explicitly re-stamped — so changing them means calling reset() and initialising again. An ask callback lets a human approve host patterns interactively, and according to the post the connection is refused whenever the callback throws or no rule covers a request.

Two sharp edges

The post flags two practical traps. First, the README still shows a SandboxRuntimeConfig constructor with twelve arguments, while the current source in the Solon AI 4.1.x tree declares thirteen, the final one a WindowsConfig; code copied from the README will not compile. Second, on Windows the string-returning wrapWithSandbox throws rather than returning a command, so that platform needs a different invocation.

Why it matters

Coding agents increasingly run with the user's own privileges, which makes the gap between "the agent can do what I can do" and "the agent can do what I allowed" the biggest factor in limiting blast radius. This module demonstrates a workable pattern — OS-enforced confinement without a container runtime — that fits the laptop workflow where interactive agents actually live. Its lineage from Claude Code's sandbox-runtime also suggests sandboxing is becoming shared infrastructure across ecosystems rather than a single-vendor feature. And the caveats are as instructive as the feature itself: asymmetric defaults, rules that update at different speeds, and documentation that has already drifted from the source are exactly the details early adopters will hit first.

  • #ai-agents
  • #java
  • #security
  • #sandboxing
  • #developer-tools

Related posts