Legacy sandbox cleanup
Remove a retired openshell-sandbox 0.0.x standalone install from a Linux host with defenseclaw sandbox legacy-cleanup, before you set up OpenShell 0.1 sandboxes.
You need this page only on a Linux host that ran the retired standalone sandbox integration. The OpenShell 0.1 sandboxes in the rest of this section do not use it. Setup asks whether you cleaned it up before it upgrades such a host (see one-time setup).
DefenseClaw no longer ships the legacy standalone sandbox integration. That
integration targeted the standalone openshell-sandbox 0.0.x binary and
OpenClaw only: it ran OpenClaw as a sandbox Linux user inside a network
namespace joined to the host by a veth pair (10.200.0.1 host,
10.200.0.2 sandbox), added iptables NAT rules, installed root systemd units
and launcher scripts, and changed ownership and ACLs on the OpenClaw home. The
per-connector sandbox policy it generated was never enforced.
The old sandbox init command and the legacy options of sandbox setup
(sandbox and host IPs, auto-pairing, host networking) were removed with it.
OpenClaw and ZeptoClaw use the shims subprocess policy on every platform;
see the capability matrix.
Detect a legacy install
On a host whose DefenseClaw config still says openshell.mode: standalone,
until cleanup runs:
- if
guardrail.hostis non-empty and notlocalhost, the gateway API keeps binding to that host (for example10.200.0.1) soupgradehealth checks keep working; see Gateway API: bind address; /healthreports asandboxsubsystem in statedegradedwhoselast_errorsays a legacy standalone install was detected. On any other host thesandboxsubsystem is absent only whileopenshell.enabledisfalse; with sandboxes on, it reports the sandbox runtime's state, as the Gateway API reference describes under Health & status; anddefenseclaw doctorwarns about the legacy install and namesdefenseclaw sandbox legacy-cleanupas the remediation.
Run cleanup
Cleanup is Linux-only. Review the plan first; --dry-run prints every step
and its exact commands without changing anything:
defenseclaw sandbox legacy-cleanup --dry-runThen run it. The plan is printed with every command, and cleanup asks once
for confirmation unless you pass --yes:
defenseclaw sandbox legacy-cleanup| Option | Behavior |
|---|---|
--dry-run | Print the plan and change nothing. |
--yes | Apply the plan without asking for confirmation. |
--remove-user | Also run userdel -r sandbox. Refused while that user has running processes, until its ownership and ACLs are gone from the OpenClaw home, or when the account's home is not the configured sandbox home. |
--remove-binary | Also remove /usr/local/bin/openshell-sandbox, only when it reports a 0.0.x version and is not owned by a package. |
Privileged steps run through sudo, with binaries resolved only from the
root-owned /usr/sbin, /usr/bin, /sbin, and /bin. Each artifact is
handled idempotently and recorded in a JSON receipt at
<data_dir>/legacy-sandbox-cleanup.json, so an interrupted run can be
repeated.
What cleanup changes
-
systemd units. Stops and disables the legacy units:
systemctl disable --now defenseclaw-sandbox.target openshell-sandbox.serviceIt removes those two unit files from
/etc/systemd/systemand the four launchers in/usr/local/lib/defenseclaw/(pre-sandbox.sh,start-sandbox.sh,post-sandbox.shandcleanup-sandbox.sh), only when they are root-owned and DefenseClaw-generated, then runssystemctl daemon-reload. -
Nothing still running. Before any later step, checks that no legacy unit is active (including one cleanup left alone because it is not DefenseClaw-generated), that no PID recorded in
<data_dir>/sandbox.pidsor<data_dir>/openshell.pidstill runs that program, and thatpgrep -u <sandbox uid>finds nothing (run through sudo when/procis mounted withhidepid, which hides other users' processes from a normal user). Otherwise cleanup stops and changes nothing else. Cleanup never runs the non-systemd launcher itself, because it lives in the operator-writable data directory; stop it first withsudo <data_dir>/scripts/run-sandbox.sh stop. -
Networking. Deletes the recorded network namespace and the host veths whose peer is in it, removes the exact iptables NAT rules the legacy launcher added (each checked with
iptables -Cfirst), and restoresnet.ipv4.conf.all.route_localnetfrom the saved value. A veth that carries10.200.0.1but cannot be tied to the recorded namespace is reported, not deleted. -
OpenClaw home. Removes the
sandboxuser's ACLs (access and default entries on the home, and its entries on every ancestor), then restores the home's original ownership from the validated backup, and removes the/home/sandbox/.openclawsymlink. On an ancestor, the backup can only clear theo+xbit legacy setup added, and only on a directory the home's owner owns; any other recorded mode is reported and left alone. A backup that disagrees with the pinnedclaw.openclaw_home_original(or with the home an earlier cleanup run recorded), names a system path, or carries a non-integer uid/gid is refused and kept. On a host where the oldsandbox setup --disablealready removed the pin and the backup, the ACLs are still removed fromclaw.home_dir(or~/.openclaw). If thesandboxaccount was already deleted, its uid is recovered from the unmapped uid that owns or has ACL entries on the home. -
OpenClaw gateway settings. Once ownership is restored, rewrites
openclaw.jsonas the invoking user to bind loopback on port18789, and points the providerbaseUrlback to localhost if it pointed at10.200.0.1. Symlinked files are refused. JSON with comments or trailing commas is accepted and written back as plain JSON. A failed rewrite is retried on the next run. -
Group membership. Removes the invoking user from the
sandboxgroup. -
Optional removals.
--remove-userand--remove-binary, as above. Neither runs by default. The group and user steps only run on a host with legacy evidence, since an account namedsandboxalone proves nothing. -
DefenseClaw config. Once the ownership and
openclaw.jsonsteps are done, clearsopenshell.mode, setsgateway.host: 127.0.0.1,gateway.port: 18789, andguardrail.host: localhost, pointsclaw.home_dirandclaw.config_fileback at the original OpenClaw home, and clearsclaw.openclaw_home_original. -
Data-dir artifacts. Backs up legacy files under the data directory to
<data_dir>/backups/legacy-sandbox-<timestamp>/, then removes them. Each file an unfinished step still needs (the ownership backup, the PID files,run-sandbox.sh) is kept until that step is done. -
Next steps. Prints the follow-up commands below.
After cleanup
While sandboxed, the agent could write anywhere in the OpenClaw home,
including openclaw.json, extensions/, skills/, and hooks/. Cleanup
only resets the gateway settings, so scan what the agent could have left
before OpenClaw runs on the host again. Then rewire the guardrail, which also
re-registers the DefenseClaw plugin and restarts the gateway and OpenClaw:
defenseclaw skill scan --all
defenseclaw plugin scan --all
defenseclaw mcp scan --all
defenseclaw setup guardrailThe openshell: config block stays in config.yaml. The legacy keys
mode and sandbox_home are read only until cleanup resets them, and
policy_dir, version, auto_pair and host_networking are accepted and
ignored; see
OpenShell sandbox settings.
Sandboxes in the TUI and macOS app
Watch and manage OpenShell sandboxes from the DefenseClaw terminal UI's Sandboxes panel or the macOS app's Sandboxes view, menu bar and notifications, and run sandbox setup from either.
ACP guard
Put DefenseClaw between an ACP editor client and coding agent to inspect prompts, streaming output, permissions, filesystem, terminal, and extension methods.