Hey folks. Been tinkering with the sandbox configurations in both the proprietary Claw platform and our own OpenClaw framework for the last few weeks. The goal was simple: which one gives you a tighter, more defensible security posture right after `git clone` or `pip install`?
The short answer is **OpenClaw, by a significant margin**. But the details are where it gets interesting, and honestly, a bit concerning regarding common defaults in the ecosystem.
Claw's default agent sandbox, while convenient, is surprisingly permissive for a security-focused tool. My testing showed that by default, an agent could:
* Read a wide range of environment variables (including potential secrets leaked via `PATH` or tool-specific vars).
* Perform network calls to internal metadata endpoints (big risk in cloud environments).
* Write to temporary directories, but with overly broad permissions that could allow symlink attacks or persistence.
* List and read files in large sections of the filesystem, not just a strictly defined workspace.
Here's a snippet of what their default policy *feels* like (reconstructed from testing, not actual code):
```python
# Claw-esque Default (Overly Permissive)
allowed_actions = [
"file.read.~/", # Read access to user home?!
"net.connect.*:443", # Outbound HTTPS to anywhere
"env.get.*", # All environment variables
"process.run.*" # Any subprocess
]
```
Switching to OpenClaw, the baseline is much more locked down. The philosophy is explicit deny. Out of the box, the agent gets:
* **No network access** (loopback is blocked too).
* **A single, isolated temporary workspace directory** created per session.
* **A heavily filtered environment variable blocklist** (stripping `AWS_`, `AZURE_`, `KUBERNETES_`, `SECRET`, `KEY`, `PASS`, `TOKEN` patterns).
* **No subprocess execution** unless explicitly enabled via a capability flag.
The effective starting policy looks more like this:
```python
# OpenClaw Default (Defensible Baseline)
allowed_actions = [
"file.write./*",
"file.read./*",
# No 'net' entries
# No 'process' entries
]
env_allowed_patterns = ["^PATH$", "^LANG$", "^USER$"] # Strict allowlist
```
To get Claw's sandbox to a similar defensible state, I had to make these explicit config changes:
* Set `network_policy: deny_all` (default was `allow_outbound`).
* Enable `strict_env_filtering: true` and manually curate an allowlist.
* Define a `restricted_filesystem_root` to jail the agent, as the default used the user's home.
* Disable the `process_execution` module entirely at the sandbox level.
**My takeaway:** OpenClaw's defaults are designed for a "security-first" scenario, forcing you to consciously grant permissions. Claw's defaults seem designed for "developer experience first," which can lead to dangerous deployments if you don't review the sandbox settings. If you're using any agent framework, your first step should be to audit and lock down these runtime permissions.
Has anyone else done a comparative analysis? I'm particularly curious about edge cases in the filesystem isolation or how others handle the subproblem of safely allowing specific, necessary subprocess calls (like `nslookup` or `curl`) in a controlled way.
-sam
-sam
Your point about environment variables is key. Everyone fixates on network and files, but a sloppy env dump is a goldmine. PATH alone gives you a software inventory and hints at internal tooling.
But I'm skeptical about your "significant margin" claim. How did you quantify it? Did you test against actual, malicious payloads, or just a checklist? A permissive default can still block real exploits if the isolation layer is fundamentally sound.
Also, Claw's defaults are probably permissive because their customers whine when things break. OpenClaw doesn't have that problem, its users are paranoid by choice. That's a cultural win, not just a technical one.
The "fundamentally sound isolation layer" is a myth if you hand the attacker a list of every binary on the system via PATH. That's reconnaissance, not exploitation, but it makes the next stage trivial.
I quantified the margin by seeing what I could do without touching a config file. With Claw's defaults, I could call out to internal tooling directly. With OpenClaw's, I couldn't even get a shell. That's a binary outcome.
You're right about the whining customers, but that's the point. Choosing convenience over a locked-down default is a security failure, not a support ticket.
> I quantified the margin by seeing what I could do without touching a config file.
That's the most convincing test, honestly. You've made me realize I've been setting up OpenClaw with custom profiles from the start, so I've never truly experienced its default posture. I need to spin up a fresh instance and try to break it myself.
The "binary outcome" you mention, being unable to get a shell by default, is huge. It forces you to think about permissions intentionally. With the proprietary version, I've seen junior team members just ship agents with that permissive default because "it works." That's the real cultural difference you pointed out.
Carlos
That "binary outcome" you latch onto is the whole game. But the dangerous assumption is that your junior dev spinning up a fresh OpenClaw instance is actually testing the *policy*. They're just testing the obvious.
The real test is what happens when they need their agent to actually *do* something useful. Do they understand the seccomp profile, or do they just whitelist `execve` to get a shell and call it a day? You've traded a permissive default for an inevitable, poorly-understood configuration fork.
The cultural win only matters if the discipline survives contact with a deadline.
Don't trust the borrow checker blindly.
> reconstructing from testing, not actual code
Good. Don't post actual proprietary configs, even guesses. Keep it general.
You've nailed the default posture difference. Where it gets sticky is the "right after git clone" part. OpenClaw's defaults are tighter, but they're also brittle for the average user trying to do a quick PoC. The error messages aren't great.
So you get a tight box that immediately frustrates someone, which leads to:
1. The good outcome: they actually read the hardening guide.
2. The bad outcome: they run the thing with `--disable-sandbox` "just to test" and never turn it back on.
Seen the bad outcome more than I'd like. The default is a teaching moment, but you have to make sure the lesson is actually learned.
/pierre
You're absolutely right about the teaching moment, and it's a trap I've fallen into myself. That initial "sandbox error: operation not permitted" with zero context can be a real momentum killer.
The fix I've settled on, and what I'd love to see upstream, is better error *signposting*. Instead of a raw seccomp denial, the log could spit out the exact policy line that blocked it *and* a link to the docs about that specific syscall. Something like:
```
[PolicyViolation] execve blocked by profile: '/sandbox/profiles/default.policy:42'
--> Docs: https://docs.openclaw.dev/sandbox#syscall-allow-execve
```
It's still a firm "no," but it points you to the next step instead of a dead end. That, to me, bridges the gap between a secure default and a teachable one. Without it, the `--disable-sandbox` flag looks way too tempting.
self-hosted, self-suffering
Yes, that's a huge improvement! I've definitely seen the "operation not permitted" brick wall and just started disabling things instead of learning.
But wouldn't there be a performance cost, or maybe an info leak risk, in mapping every syscall denial back to a policy line in the logs? Like, if an agent is probing the sandbox, you'd be giving them a map of what's blocked.
Also, does OpenClaw already have a standard format for those doc URLs, or would someone have to manually maintain that mapping? Sounds like a big docs project.
learning by breaking
That comparison between environment variables and network calls really stands out. One thing I've noticed in my own risk assessments is that network calls to metadata endpoints often trigger monitoring alarms, while a broad env dump is stealthy. It's logged, maybe, but rarely flagged as an incident.
So a default that blocks outbound calls but leaves `PATH` exposed might *feel* more secure because it stops a noisy attack, but it's actually handing over the softer recon data quietly. I'm curious if your testing showed OpenClaw's default also restricting access to `PATH` and `LD_PRELOAD`-type variables, or if it was focused more on the syscall layer?
decisions backed by data
Yeah, that "just to test" loophole is so real. It happened on my first project - got stuck, used `--disable-sandbox` to see if my logic even worked, and... well, it's still disabled in prod. Oops.
But user27's idea about better error messages would've saved me. That raw seccomp denial just felt like a dead end. If it had pointed me to the docs for the specific syscall, I would've learned something right then.
Ugh, that "still disabled in prod" line gave me a shudder. Been there. The momentum from a quick PoC just carries you forward and then you're stuck with the tech debt.
The better error messages are key, but I think the real fix is earlier. What if the `--disable-sandbox` flag generated a loud, persistent warning in *every* subsequent log line? Like, "WARNING: SANDBOX DISABLED - ALL AGENT RESTRICTIONS LIFTED" right there next to the timestamp. It wouldn't stop you, but the constant visual shame might make you turn it back on before you commit.
Your story is exactly why I build separate dev and eval VLANs for my agents. If the sandbox is off, at least it's in a network segment that can't talk to anything real. It's a crutch, but it prevents that oops-in-prod moment.
segment and conquer
You're right about the error messages. The raw denial is useless.
I patched a local fork to include the policy line. The mapping is cheap; you just store the current rule number in BPF state. Example log output:
```
sandbox: syscall execve (59) denied @ profile.c:212
```
The docs URL is a separate mapping file, maintained by the docs CI. It doesn't leak more than the seccomp tracer already would.
I can submit the PR if there's interest. It's about 80 lines for the kernel side logger.