151 comments

[ 3.4 ms ] story [ 88.6 ms ] thread
What would it take for people to stop recklessly running unconstrained AI agents on machines they actually care about? A Stanford researcher thinks the answer is a new lightweight Linux container system that you don't have to configure or think about.
unconstrained AI agents are what makes it so useful though. I have been using claude for almost a year now and the biggest unlock was to stop being a worrywart early on and just literally giving it ssh keys and telling it to fix something. ofc I have backups and do run it in VM but in that VM it helps me manage by infra and i have a decent size homelab that would be no fun but a chore without this assistant.
There always has been this tension between protecting resources and allowing users to access those resources in security. With many systems you have admin/root users and regular users. Some things require root access. Most interesting things (from a security point of view) live in the user directory. Because that's where users spend all their time. It's where you'll find credentials, files with interesting stuff inside, etc. All the stuff that needs protecting.

The whole point of using a computer is being able to use it. For programmers, that means building software. Which until recently meant having a lot of user land tools available ready to be used by the programmer. Now with agents programming on their behalf, they need full access to all that too in order to do the very valuable and useful things they do. Because they end up needing to do the exact same things you'd do manually.

The current security modes in agents are binary. Super anal about absolutely everything; or off. It's a false choice. It's technically your choice to make and waive their liability (which is why they need you to opt in); but the software is frustrating to use unless you make that choice. So, lots of people make that choice. I'm guilty as well. I could approve every ansible and ssh command manually (yes really). But a typical session where codex follows my guardrails to manage one of my environments using ansible scripts it maintains just involves a whole lot such commands. I feel dirty doing it. But it works so well that doing all that stuff manually is not something I want to go back to.

It's of course insecure as hell and I urgently need something better than yolo mode for this. One of the reasons I like codex is that (so far) it's pretty diligent about instruction following and guard rails. It's what makes me feel slightly more relaxed than I perhaps should be. It could be doing a lot of damage. It just doesn't seem to do that.

Excellent project, unfortunate title. I almost didn't click on it.

I like the tradeoff offered: full access to the current directory, read-only access to the rest, copy-on-write for the home directory. With stricter modes to (presumably) protect against data exfiltration too. It really feels like it should be the default for agent systems.

What would Jonathan Blow think about this.
How is this different than say bubblewrap and others?
Claude's stock unprompted / uninspired UI code creates carbon clone components. That "jai is not a promise of perfect safety" callout box is like the em dash of FE code. The contrast, or lack thereof, makes some of the text particularly invisible.

I wonder if shitty looking websites and unambitious grammar will become how we prove we are human soon.

(comment deleted)
Add this to .claude/settings.json:

  {                                                                                                                                                              
    "sandbox": {                                                                                                                                               
      "enabled": true,
      "filesystem": {
        "allowRead": ["."],
        "denyRead": ["~/"],
        "allowWrite": ["."],
        "denyWrite": ["/"]
      }                                                                                                                                                          
    }
  }

You can change the read part if you're ok with it reading outside. This feature was only added 10 days ago fwiw but it's great and pretty much this.
I noticed codex has a sandbox, wondering if it has a comparable config section.
I think the point would be that - some random upcoming revision of claude-code could remove or simply change the config name just as silently as it was introduced.

People might genuinely want some other software to do the sandboxing. Something other than the fox.

Is this a real sandbox or just a pretty please?
Interesting, thanks. I use remote ephemeral dev containers with isolated envs, so filesystem damage isn't really a concern as long as the PR looks good in review. Nice extra guardrail though, will add it to the project-level settings.
It will just do

    ssh you@localhost "rm -rf ~"
Not if the sandbox rule forbids reading the private key and the ssh agent socket (as the shown example does)
I've seen claude get confused about what directory it's in. And of course I've seen claude run rm -rf *. Fortunately not both at the same time for me, but not hard to imagine. The claude sandbox is a good idea, but to be effective it would need to be implemented at a very low level and enforced on all programs that claude launches. Also, claude itself is an enormous program that is mostly developed by AI. So to have a small <3000-line human-implemented program as another layer of defense offers meaningful additional protection.
I use bbwrap to sandbox Claude. Works very well and gives me a lot of control and certainty around the sandbox.
lol if you think Claude is smart enough to block sneaky path strings based on your config.
Does this also apply to the commands or programs that it runs?

e.g. if it writes a script or program with a bug which affects other files, will this prevent it from deleting or overwriting them?

What about if the user runs a program the agent wrote?

1. Yes this configuration applies to the sandbox where the commands executed by Claude are run and as such it applies to anything these commands do, including child processes etc

2. The sandbox rules also apply to the program written by the agent IF you ask Claude to run that program. If you run it manually from another she'll or via the "!" directive from within Claude, the sandbox won't be used

Also, a lot of people use multiple harnesses. I'm often switching between claude, codex, and opencode. It's kind of nice to have the sandbox policy independent of the actual AI assistant you are running.
So in some sense we start recreating an operating system, or at least the userspace, within the Claude code. There was some name for this pattern but I can’t recall
It’s cute because Claude has discretion to disable its own sandbox and does it
I’m surprised it works for you with such a simple config? I’m the one that added the allowRead option to Claude’s underlying sandbox [0] and had quite a job getting my toolchains and skills to work with it [1].

[0] Fun to see the confusing docs I wrote show up more or less verbatim on Claude’s docs.

[1] My config is here, may be useful to someone: https://github.com/carderne/pi-sandbox/blob/main/sandbox.jso...

Is this a hard sandbox (enforced outside the LLM)?
And you'd trust that given CC is a vibe-coded mess?

Editing to go even further because, I gotta say, this is a low point for HN. Here's a post with a real security tool and the top comment is basically "nah, just trust the software to sandbox itself". I feel like IQ has taken a complete nosedive in the past year or so. I guess people are already forgetting how to think? Really sad to see.

It's common practice to ask the agent to refer to another project, in that case I guess the read should point to the root folder of the projects.

Also, any details on how is this enforced? because I notice that the claude in Windows don't respect plan mode always; It has edited files in plan mode; I never faced that issue in Linux though.

The sandbox only limits what processes spawned by Claude can do. Claude itself can read from any directory you tell it to read from (i.e. that's a different permission mechanism)
I've had issues with the sandbox feature, both on linux (archlinux) and two macos machines (tahoe). There is an open issue[1] on the claude-code issue tracker for it.

I'm not saying it is broken for everyone, but please do verify it does work before trusting it, by instructing Claude to attempt to read from somewhere it shouldn't be allowed to.

From my side, I confirmed both bubblewrap and seatbelt to work independently, but through claude-code they don't even though claude-code reports them to be active when debugging.

[1] https://github.com/anthropics/claude-code/issues/32226

I'm now considering installing QubesOS for all dev work to absolutely ensure all coding agents run in secure separate sandboxes together without any OS level exposure.
FYI, this doesn’t always work as expected. Try asking Claude to read “~/.ssh/config” with these settings and it will happily do it.

Specifically, it only works for spawned processes and not builtin tools.

For some reason, this made everything worse for me. Now claude constantly tries to access my home folder instead of current directory. Obviously this is not still good enough. Also Claude keeps dismissing my instructions on not to read my home directory and use current directory. Weird.
I have the same problem. If my sandbox includes `denyRead: ["~"]`, claude consistently tries to do things inside my home directory. For example, every time I start claude I tell it to "run pwd".

And every time it says this:

    Bash(pwd)  
      ⎿  /home/<username>  
      ⎿  Shell cwd was reset to /home/<username>/Projects/<current-working-dir>
This breaks a bunch of features in inconsistent ways (e.g., `git status` sometimes works and sometimes doesn't).

There are issues reporting this problem to Anthropic but they are all closed with no helpful comments:

https://github.com/anthropics/claude-code/issues/11067

https://github.com/anthropics/claude-code/issues/17053

https://github.com/anthropics/claude-code/issues/27255

Cool. Does opencode.ai have such a feature also (sandboxing with bubblewrap)?
You do also have to worry about exec and other neat ways to probably get around stuff. You could also spin up YAD (yet another docker) and run Claude in there with your git cloned into it and beyond some state-level-actor escapes it should cover 99% of your most basic failures.
So what does this do exactly? If it used "default deny" or "default allow" you wouldn't have both allow and deny rules...
Did you get this to work with docker where the agent/dev env would work on the host machine but the stack itself via docker compose?

Many of the projects I work on follow this pattern (and I’m not able to make bigger changes in them) and sanboxing breaks immediately when I need to docker compose run sometask.sh

(comment deleted)
Interesting point. I've been running an autonomous multitalented AI agent (Aegis) on a $100 Samsung A04e. It manages 859 referring sites without touching the local filesystem much. Efficiency over hardware works."
I know many 'Senior Engineers' will say 85ns is impossible on a $100 Cortex-A53 device. They'll say you need a $10k server. I've proven them wrong. Here is why your architecture is probably slower than my A04e..."
Battle hardened tools for this have existed for decades, we don't need new ones. Just run claude as a user without access to those directories, that way the containment is inherited by subprocesses.
Alternatively, the "feel free to leak all my data but please use my GPUs and don't rm -rf /" config:

  {
    "sandbox": {
      "enabled": true,
      "filesystem": {
        "allowRead": ["/"],
        "allowWrite": [
          ".",
          "/tmp",
          "/dev/nvidia0",
          "/dev/nvidia1",
          "/dev/nvidia2",
          "/dev/nvidia3",
          "/dev/nvidia4",
          "/dev/nvidia5",
          "/dev/nvidia6",
          "/dev/nvidia7",
          "/dev/nvidia8",
          "/dev/nvidiactl",
          "/dev/nvidia-uvm"
        ]
      }
    }
  }
Any way to have it use /Users/claude/*? or something like that
what does this do?
Suggestion for the FAQ page: does this work on a Mac?
Should be named Jia

More seriously, I'm not a heavy agent user, but I just create a user account for the agent with none of my own files or ssh keys or anything like that. Hopefully that's safe enough? I guess the risk is that it figures out a local privilege escalation exploit...

This still is running in an isolated container, right?

Ignoring the confidentiality arguments posed here, I can’t help to think about snapshotting filesystems in this context. Wouldn’t something like ZFS be an obvious solution to an agent deleting or wildly changing files? That wouldn’t protect against all issue the authors are trying to address, but it seems like an easy safeguard against some of the problems people face with agents.

The examples in the article are all big scary wipes, But I think the more common damage is way smaller and harder to notice.

I've been using claude code daily for months and the worst thing that happened wasnt a wipe(yet). It needed to save an svg file so it created a /public/blog/ folder. Which meant Apache started serving that real directory instead of routing /blog. My blog just 404'd and I spent like an hour debugging before I figured it out. Nothing got deleted and it's not a permission problem, the agent just put a file in a place that made sense to it.

jai would help with the rm -rf cases for sure but this kind of thing is harder to catch because its not a permissions problem, the agent just doesn't know what a web server is.

Should definitely block .ssh reading too...
I want agents to modify the file system. I want them to be able to manage my computer if it thinks it's a good idea. If a build fails due to running out of disk space I want it to be able to find appropriate stuff to delete to free up space.
Not sure I understand the problem. Are people just letting AI do anything? I use Claude Code and it asks for permission to run commands, edit files, etc. No need for sandbox
I've done some experimenting with running a local model with ollama and claude code connecting to it and having both in a firejail: https://firejail.wordpress.com/ What they get access to is very limited, and mostly whitelisted.
For jailing local agents on a Mac, I made Agent Safehouse - it works for any agent and has many sane default for developers https://agent-safehouse.dev
I've been reviewing Agent sandboxing solutions recently and it occurred to me there is a gaping vector for persistent exploits for tools that let the agent write to the project directory. Like this one does.

I had originally thought this would ok as we could review everything in the git diff. But, it later occurred to me that there are all kinds of files that the agent could write to that I'd end up executing, as the developer, outside the sandbox. Every .pyc file for instance, files in .venv , .git hook files.

ChatGPT[1] confirms the underlying exploit vectors and also that there isn't much discussion of them in the context of agent sandboxing tools.

My conclusion from that is the only truly safe sandboxing technique would be one that transfers files from the sandbox to the dev's machine through some kind of git patch or similar. I.e. the file can only transfer if it's in version control and, therefore presumably, has been reviewed by the dev before transfer outside the sandbox.

I'd really like to see people talking more about this. The solution isn't that hard, keep CWD as an overlay and transfer in-container modified files through a proxy of some kind that filters out any file not in git and maybe some that are but are known to be potentially dangerous (bin files). Obviously, there would need to be some kind of configuration option here.

1: https://chatgpt.com/share/69c3ec10-0e40-832a-b905-31736d8a34...

i just use seatbelt (mac native) in my custom coding agent: supercode
I'd really like to try this, but building it is impossible. C++ is such a pain to build with the "`make`; hunt for the dependency that failed; `apt-get install whatever-dev`; goto make" loop...

Please release binaries if you're making a utility :(

Interesting take on the same problem

I created https://github.com/jrz/container-shell which basically launches a persistent interactive shell using docker, chrooted to the CWD

CWD is bind mounted so the rest is simply not visible and you can still install anything you want.