[HN Gopher] Show HN: Zerobox - Sandbox any command with file, ne...
       ___________________________________________________________________
        
       Show HN: Zerobox - Sandbox any command with file, network,
       credential controls
        
       I'm excited to introduce Zerobox, a cross-platform, single binary
       process sandboxing CLI written in Rust. It uses the sandboxing
       crates from the OpenAI Codex repo and adds additional
       functionalities like secret injection, SDK, etc.  Watch the demo:
       https://www.youtube.com/watch?v=wZiPm9BOPCg  Zerobox follows the
       same sandboxing policy as Deno which is deny by default. The only
       operation that the command can run is reading files, all writes and
       network I/O are blocked by default. No VMs, no Docker, no remote
       servers.  Want to block reads to /etc?                 zerobox
       --deny-read=/etc -- cat /etc/passwd            cat: /etc/passwd:
       Operation not permitted       How it works:  Zerobox wraps any
       commands/programs, runs an MITM proxy and uses the native
       sandboxing solutions on each operating system (e.g BubbleWrap on
       Linux) to run the given process in a sandbox. The MITM proxy has
       two jobs: blocking network calls and injecting credentials at the
       network level.  Think of it this way, I want to inject "Bearer
       OPENAI_API_KEY" but I don't want my sandboxed command to know about
       it, Zerobox does that by replacing "OPENAI_API_KEY" with a
       placeholder, then replaces it when the actual outbound network call
       is made, see this example:                 zerobox --secret
       OPENAI_API_KEY=$OPENAI_API_KEY --secret-host
       OPENAI_API_KEY=api.openai.com -- bun agent.ts       Zerobox is
       different than other sandboxing solutions in the sense that it
       would allow you to easily sandbox any commands locally and it works
       the same on all platforms. I've been exploring different sandboxing
       solutions, including Firecracker VMs locally, and this is the
       closest I was able to get when it comes to sandboxing commands
       locally.  The next thing I'm exploring is `zerobox claude` or
       `zerobox openclaw` which would wrap the entire agent and preload
       the correct policy profiles.  I'd love to hear your feedback,
       especially if you are running AI Agents (e.g. OpenClaw), MCPs, AI
       Tools locally.
        
       Author : afshinmeh
       Score  : 86 points
       Date   : 2026-03-30 14:32 UTC (2 days ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | alyxya wrote:
       | Cool project, and I think there would be a lot of value in just
       | logging all operations.
        
         | kimixa wrote:
         | For just logging would it really give any more info than a
         | trace already does?
        
           | alyxya wrote:
           | Forgot about that, was mostly thinking about how AI agents
           | with unrestricted permissions would ideally have some
           | external logging and monitoring, so there would be a record
           | of what it touched. A trace has all of the raw information,
           | so some kind of wrapper around that would be useful.
        
             | afshinmeh wrote:
             | I'd like to know what level of details you'd expect.
             | Something like `zerobox -- claude`, then you get an output
             | log like this:
             | 
             | ```
             | 
             | Read file /etc/passwd
             | 
             | Made network call to httpbin.org
             | 
             | Write file /tmp/access
             | 
             | ```
             | 
             | etc.? I'm really interested to hear your thoughts and I
             | will add that feature (I need something like that, too).
        
           | kimixa wrote:
           | *strace that is - annoyingly it seems it was autocorrected
           | away
        
             | afshinmeh wrote:
             | I think there is still a valid case for sandbox logs/otel.
             | strace would give you the syscalls/traces but not _why_ a
             | particular call was blocked in side the sandbox (e.g. the
             | decision making bit).
        
         | afshinmeh wrote:
         | Agreed. I added the `--debug` flag this morning. It does simple
         | logging including the proxy calls:
         | 
         | ```
         | 
         | $ zerobox --debug --allow-net=httpbin.org -- curl
         | 
         | 2026-04-01T18:06:33.928486Z CONNECT blocked
         | (client=127.0.0.1:59225, host=example.com, reason=not_allowed)
         | 
         | curl: (56) CONNECT tunnel failed, response 403
         | 
         | ```
         | 
         | I'm planning on adding otel integration as well.
        
       | eluded7 wrote:
       | Personally I would probably always reach for a docker container
       | if I want a sandboxed command that can run identically anywhere.
       | 
       | I appreciate that alternate sandboxing tools can reduce some of
       | the heavier parts of docker though (i.e. building or downloading
       | the correct image)
       | 
       | How would you compare this tool to say bubblewrap
       | https://github.com/containers/
        
         | ebb_earl_co wrote:
         | The text says that it uses OS-level tools, specifically bubble
         | wrap on Linux.
        
           | afshinmeh wrote:
           | That's right. It uses the same kernel mechanisms as Docker,
           | the runtime is different though (bwrap on linux, seatbelt on
           | mac, etc.)
        
         | hrmtst93837 wrote:
         | Docker shares the host kernel, so a container escape lands on
         | your box, and bubblewrap stays lighter but it leak edges if you
         | leave seccomp or fs mounts loose.
         | 
         | Zerobox reads like a tool for per-command guardrails instead of
         | image management. That trade looks saner for local runs, though
         | it's new enough that I'd expect a few escapes before the rough
         | egdes are gone.
        
       | time0ut wrote:
       | Very interesting. I just started researching this topic yesterday
       | to build something for adjacent use cases (sandboxing LLM
       | authored programs). My initial prototype is using a wasm based
       | sandbox, but I want something more robust and flexible.
       | 
       | Some of my use cases are very latency sensitive. What sort of
       | overhead are you seeing?
        
         | afshinmeh wrote:
         | I added a benchmark test (Apple M5) and on average I'm seeing
         | 10ms overhead. I added a benchmark section to the repo as well
         | https://github.com/afshinm/zerobox?tab=readme-ov-file#perfor...
         | 
         | Also, I'm literally wrapping Claude with zerobox now! No
         | latency issues at all.
        
         | qalfy wrote:
         | Wasm sandboxes are fast for pure compute but get painful the
         | moment LLM code needs filesystem access or subprocess spawning.
         | And it will, constantly. Containers with seccomp filters give
         | you near-native speed and way broader syscall support --
         | overhead is basically startup time (~2s cold, sub-second warm).
         | For anything IO-heavy it's not even close. We're doing
         | throwaway containers at https://cyqle.in if anyone's curious.
        
           | afshinmeh wrote:
           | I will run the same benchmark test on wasm sandboxes just to
           | be able to compare it with Zerobox. I will share the results
           | tomorrow.
        
         | afshinmeh wrote:
         | Here is the video, running Claude with Zerobox, you can see the
         | latency, etc. https://www.youtube.com/watch?v=xzsGsSsx0OI
        
       | jbverschoor wrote:
       | Again, it's blacklisting so kind of impossible to get right. I've
       | looked at this many times, but in order for things to properly
       | work, you have to create a huge, huge, huge, huge sandbox file.
       | 
       | Especially for your application that you any kind of Apple
       | framework.
        
         | simonw wrote:
         | This doesn't look like it's blacklisting to me. It's an
         | allowlist system:                 --allow-net=api.openai.com #
         | Explicitly allow access to that host            --allow-
         | write=config.txt # Explicitly allow write to that file
        
           | afshinmeh wrote:
           | That's correct. The pattern is: reads allowed, write and
           | network I/O blocked by default.
           | 
           | ```
           | 
           | zerobox -- curl https://example.com
           | 
           | Could not resolve host: example.com
           | 
           | ```
        
             | simonw wrote:
             | Oh so it allows ALL file reads?
             | 
             | I'd feel safer with default-deny on reads as well, but I
             | know from past experience that this gets tricky fast -
             | tools like Node.js and uv and Python all have a bunch of
             | files they need to be able to read that you might not
             | predict in advance.
             | 
             | Might still be possible to do that in a DX-friendly way
             | though, if you make it easy to manually approve reads the
             | first time and use that to build a profile that can be
             | reused on subsequent command invocations.
        
               | afshinmeh wrote:
               | I agree and you can deny all reads like this:
               | 
               | ```
               | 
               | zerobox --deny-read=/ -- cat /etc/passwd
               | 
               | ```
               | 
               | That being said, what the default DX shouldl be? What
               | paths to deny by default? That's something I've been
               | thinking about and I'd love to hear your thoughts.
        
               | simonw wrote:
               | That's a really tough question. I always worry about
               | credentials that are tucked away in ~/.folders in my home
               | directory like in ~/.aws - but you HAVE to provide access
               | to some of those like ~/.claude because otherwise Claude
               | Code won't work.
               | 
               | That's why rather than a default set I'm interested in an
               | option where I get to approve things on first run - maybe
               | something like this:                 zerobox --build-
               | profile claude-profile.txt -- claude
               | 
               | The above command would create an empty claude-
               | profile.txt file and then give me a bunch of interactive
               | prompts every time Claude tried to access a file, maybe
               | something like:                 claude wants to read
               | ~/.claude/config.txt       A) allow that file, D) allow
               | full ~/.claude directory, X) exit
               | 
               | You would then clatter through a bunch of those the first
               | time you run Claude and your decisions would be written
               | to claude-profile.txt - then once that file exists you
               | can start Claude in the future like this:
               | zerobox --profile claude-profile.txt -- claude
               | 
               | (This is literally the first design I came up with after
               | 30s of thought, I'm certain you could do much better.)
        
               | afshinmeh wrote:
               | Fantastic! I like that idea. I'm also exploring an option
               | to define profiles, but also have predefines profiles
               | that ships with the binary (e.g. Claude, then block all
               | `.env` reads, etc.)
        
               | simonw wrote:
               | Being able to mix and match profiles would be neat.
        
               | afshinmeh wrote:
               | Give me 2 days :)
        
         | afshinmeh wrote:
         | That's interesting, thanks for sharing that. Could you
         | elaborate a bit more? I'd like to understand the use case is a
         | bit better.
        
       | wepple wrote:
       | You should probably add a huge disclaimer that this is an
       | untested, experimental project.
       | 
       | Related, a direct comparison to other sandboxes and what you
       | offer over those would be nice
        
         | afshinmeh wrote:
         | I agree to some extend. I'm using the OpenAI Codex crates for
         | sandboxing though, which I think it's properly tested? They
         | launched last year and iterated many times. I will add a note
         | though, thanks!
        
       | simonw wrote:
       | This looks really good - the CLI interface design is solid, and I
       | especially like the secrets / network proxy pattern - but the
       | thing it needs most is _copiously detailed_ documentation about
       | exactly how the sandbox mechanism works - and how it was tested.
       | 
       | There are dozens of projects like this emerging right now. They
       | all share the same challenge: establishing credibility.
       | 
       | I'm loathe to spend time evaluating them unless I've seen robust
       | evidence that the architecture is well thought through and the
       | tool has been extensively tested already.
       | 
       | My ideal sandbox is one that's been used by hundreds of people in
       | a high-stakes environment already. That's a tall order, but if
       | I'm going to spend time evaluating one the next best thing is
       | documentation that teaches me something about sandboxing and
       | demonstrates to me how competent and thorough the process of
       | building this one has been.
       | 
       | UPDATE: On further inspection there's a lot that I like about
       | this one. The CLI design is neat, it builds on a strong
       | underlying library (the OpenAI Codex implementation) and the
       | features it does add - mainly the network proxy being able to
       | modify headers to inject secrets - are genuinely great ideas.
        
         | afshinmeh wrote:
         | Simon! Thanks. I appreciate your comment and totally agreed. I
         | will improve the docs as well as tests.
        
         | kjok wrote:
         | > There are dozens of projects like this emerging right now.
         | They all share the same challenge: establishing credibility.
         | 
         | Care to elaborate on the kind of "credibility" to be
         | established here? All these bazillion sandboxing tools use the
         | same underlying frameworks for isolation (e.g., ebpf, landlock,
         | VMs, cgroups, namespaces) that are already credible.
        
           | simonw wrote:
           | The problem is that those underlying frameworks can very
           | easily be misconfigured. I need to know that the higher level
           | sandboxing tools were written by people with a _deep_
           | understanding of the primitives that they are building on,
           | and a very robust approach to testing that their assumptions
           | hold and they don 't have any bugs in their layer that affect
           | the security of the overall system.
           | 
           | Most people are building on top of Apple's sandbox-exec which
           | is itself almost entirely undocumented!
        
             | kjok wrote:
             | > The problem is that those underlying frameworks can very
             | easily be misconfigured.
             | 
             | Agreed. I'm sure a number of these sandboxing solutions are
             | vibe-coded, which makes your concerns regarding
             | misconfigurations even more relevant.
        
       | zephyrwhimsy wrote:
       | Technical debt is not always bad. Deliberate technical debt taken
       | on with eyes open to ship faster is a legitimate business
       | strategy. The problem is accidental technical debt from poor
       | decisions compounding silently.
        
       | volume_tech wrote:
       | the credential injection via MITM proxy is the most interesting
       | part to me. the standard approach for agents is environment
       | variables, which means the agent process can read them directly.
       | having the sandbox intercept network calls and swap in
       | credentials at the proxy layer means the agent code has a
       | placeholder and never sees the real value -- useful when running
       | less-trusted agent code or third-party tools.
       | 
       | the deny-by-default network policy also matters specifically for
       | agent use: without it there is nothing stopping a tool call from
       | exfiltrating context window contents to an arbitrary endpoint.
       | most sandboxes focus on filesystem isolation and treat network as
       | an afterthought.
        
         | afshinmeh wrote:
         | Thanks and agreed! Zerobox uses the Deno sandboxing policy and
         | also the same pattern for cred injection (placeholders as env
         | vars, replaced at network call time).
         | 
         | Real secrets are never readable by any processes inside the
         | sandbox:
         | 
         | ```
         | 
         | zerobox -- echo $OPENAI_API_KEY
         | 
         | ZEROBOX_SECRET_a1b2c3d4e5...
         | 
         | ```
        
           | simonw wrote:
           | Do you know if there's a widely shared name for this pattern?
           | I've been collecting examples of it recently - it's a really
           | good idea - but I'm not sure if there's good terminology.
           | "Credential injection" is one option I've seen floating
           | around.
        
             | afshinmeh wrote:
             | Not sure. I took this idea from the Deno sandboxing docs.
             | They also do the exact same thing, different sandboxing
             | mechanism though (I think Deno has it's own way of
             | sandboxing subprocesses).
        
             | TheTaytay wrote:
             | simonw, I have been seeing "credential injection" and
             | "credential tokenizing" (a la tokenizer:
             | https://github.com/superfly/tokenizer). I'm also seeing
             | credential "surrogates" mentioned.
             | 
             | I am currently working on a mitm proxy for use with
             | devcontainers to try to implement this pattern, but I'm
             | certainly not the only one!
        
               | simonw wrote:
               | Thanks, I think I'll go with "credential injection" since
               | the word "tokenization" has other meanings that I find
               | confusing here.
        
         | gbibas wrote:
         | This is the right direction. Running AI coding agents in
         | production, the scariest moment is when an agent needs API
         | access to do its job but you can't trust what it'll do with
         | those credentials. We ended up with a simpler version of this:
         | each agent runs in an isolated git worktree with only the env
         | vars it specifically needs, and network access restricted to
         | localhost + our API. No MITM proxy, just a stripped-down
         | environment.
         | 
         | The deny-by-default model is correct. The question is how
         | granular you need to be. For AI agents, I'd argue coarse-
         | grained is better -- network yes/no, filesystem scoped to one
         | directory, no credential access. Fine-grained permissions add
         | complexity the agent will just work around anyway.
        
       | mdavid626 wrote:
       | I trust sandbox-exec more, or Docker on Linux. Those come from
       | the OS, well tested and known.
       | 
       | MITM proxy is nice idea to avoid leaking secrets. Isn't it very
       | brittle though? Anthropic changes some URL-s and it'll break.
        
         | afshinmeh wrote:
         | Thanks for sharing that. Zerobox _does_ use the native OS
         | sandboxing mechanisms (e.g. seatbelt) under the hood. I'm not
         | trying to reinvent the wheel when it comes to sandboxing.
         | 
         | Re the URLs, I agree, that's why I added wildcard support, e.g.
         | `*.openai.com` for secret injection as well as network call
         | filtering.
        
           | mdavid626 wrote:
           | How do you intercept network traffic on mac os? How do you
           | fake certificates?
        
             | afshinmeh wrote:
             | Zerobox creates a cert in `~/.zerobox/cert` on the first
             | proxy run and reuses that. The MTIM process uses that cert
             | to make the calls, inject certs, etc. This is actually done
             | by the underlying Codex crate.
        
               | mdavid626 wrote:
               | Yeah, but how does the sandboxed process "know" that it
               | has to go through the proxy? How does it trust your
               | certificate? Is the proxy fully transparent?
        
               | afshinmeh wrote:
               | Oh I see. It inject HTTP_PROXY/HTTPS_PROXY/etc. env vars
               | into the process so that all sandboxed subprocesses go
               | through the proxy.
        
           | mdavid626 wrote:
           | You know, the thing is, that it is super easy to create such
           | tools with AI nowadays. ...and if you create your own, you
           | can avoid these unnecessary abstractions. You get exactly
           | what you want.
        
       | nonameiguess wrote:
       | This is more a criticism of codex's linux-sandboxing, which
       | you're just wrapping, but it's the first I've ever looked at it.
       | I don't see how it makes sense to invoke bwrap as a forked
       | subprocess. Bubblewrap can't do anything beyond what you can do
       | with unshare directly, which you can simply invoke as a system
       | call without needing to spawn a subprocess or requiring the user
       | to have bwrap installed. It kinds of reeks of amateur hour when
       | developers effectively just translate shell scripts into compiled
       | languages by using whatever variant of "system" is available to
       | make the same command invocations you would make through a shell,
       | as opposed to actually using the system call API. Especially when
       | the invocation is crafted from user input, there's a long history
       | of exploits arising from stuff like this. Writing it in Rust does
       | nothing for you when you're just using Rust to call a different
       | CLI tool that isn't written in Rust.
        
         | afshinmeh wrote:
         | Thanks for sharing this, I read your comment multiple times.
         | What would be the alternative though? It is true that the
         | program being written in Rust doesn't solve the problem of
         | spawning subprocesses, but what's the alternative in that case?
        
         | simonw wrote:
         | Is your criticism here that there's no point in invoking bwrap
         | directly when you could instead implement the same things that
         | bwrap implements?
         | 
         | I'd much rather a system call bwrap than re-implement bwrap,
         | because bwrap has already been extensively tested.
        
           | afshinmeh wrote:
           | That was my thinking, too. The only other option would be
           | reimplement it in Rust (never researched what exists though).
        
       | gigatexal wrote:
       | there's been so many of these -- which of these sandboxing tools
       | is best?
        
         | _pdp_ wrote:
         | Not a single one. All of them are solving the obvious (and
         | wrong) problem.
        
           | afshinmeh wrote:
           | I'd love to learn more please. I'm interested in sandboxing
           | AI tools/agents regardless of the underlying mechanism (I
           | explored Firecracker VMs briefly as well, terrible cross
           | platform support though).
        
           | simonw wrote:
           | What's the right problem to be solving here?
        
       | EGreg wrote:
       | This is really useful! How well does it compare though to Docker
       | etc.
       | 
       | Because I am worried about sandbox escapes. This is what we
       | currently use to sandbox JS inside Browsers and Node (without
       | anything extra) :
       | https://github.com/Qbix/Platform/blob/main/platform/plugins/...
       | 
       | I like tools like this, but they all seem to share the same
       | underlying shape: take an arbitrary process and try to restrict
       | it with OS primitives + some policy layer (flags, proxies, etc).
       | 
       | That works, but it also means correctness depends heavily on
       | configuration, i.e. you're starting with a lot of ambient
       | authority and trying to subtract from it enforcement ends up
       | split across multiple layers (kernel, wrapper, proxy)
       | 
       | An alternative model is to flip it: Instead of sandboxing
       | arbitrary programs, run workflows in an environment where there
       | is no general network/filesystem access at all, and every
       | external interaction has to go through explicit capabilities.
       | 
       | In that setup, there's nothing to "block" because the dangerous
       | primitives aren't exposed, execution can be
       | deterministic/replayable, so you can actually audit behavior.
       | Thus, secrets don't enter the execution context, they're only
       | used at the boundary
       | 
       | It feels closer to capability-based systems than traditional
       | sandboxing. Curious how people here think about that tradeoff vs
       | OS-level sandbox + proxy approaches.
        
         | afshinmeh wrote:
         | Zerobox uses the same kernel mechanisms (namespaces + seccomp)
         | but no daemon, no root and cold start ~10ms (Docker is much
         | worse in that regard).
         | 
         | Docker gives you full filesystem isolation and resource limits.
         | Zerobox gives you granular file/network/credential controls
         | with near zero overhead. You can in fact use Zerobox _inside_
         | Docker (e.g. for secret management)
        
       | smallerfish wrote:
       | Compare with and steal any ideas you like from mine if you like.
       | I've got a semi-decent curl|bash pattern covered, and also add
       | network filtering via pasta (which may be more robust than
       | rolling your own). https://github.com/reubenfirmin/bubblewrap-tui
        
         | afshinmeh wrote:
         | Ohh! thanks for sharing this. You are using DNS proxy which is
         | interesting and useful if a process doesn't respect the
         | HTTPS_PROXY/HTTP_PROXY/etc. env vars that I'm injecting. I will
         | take a look, very interesting.
        
       | dk8996 wrote:
       | Very cool. Is there a way to have a notion of a session, saving
       | state between runs?
        
         | afshinmeh wrote:
         | No, it's stateless right now. What is your requirement though?
         | How do you define a session? Are you referring to
         | "snapshotting" between sessions?
        
       | jwilliams wrote:
       | It's terrific to see this. I'm definitely going to give it a
       | whirl. I've been working on a specific JavaScript isolate[^1].
       | This is great source of inspiration for it.
       | 
       | [^1]: https://github.com/jonathannen/hermit
        
         | afshinmeh wrote:
         | I'd love to hear your thoughts! I've been primarily testing
         | this with Bun + Vercel AI SDK for tool call sandboxing.
        
       | Lethalman wrote:
       | Wish it wasn't rust... it's so hard to read.
        
         | afshinmeh wrote:
         | I know. I will add more docs soon though, that should make it
         | easier to navigate the code and understand what's going on.
        
       | lights0123 wrote:
       | > zerobox --secret OPENAI_API_KEY=$OPENAI_API_KEY
       | 
       | Linux by default allows all users to read CLI arguments of
       | running processes. While it looks like your bwrap invocation
       | prevents the sandbox from looking at this process (--unshare-
       | pid), any other process running on your system can read the
       | secret.
        
         | afshinmeh wrote:
         | That's true and the expected behaviour but I see your point.
         | The example there is not great, I should've used `sk_s123...`
         | to show that you are passing the env var to the sandbox as
         | opposed to setting it on the host, then proxying it. I will
         | update it.
        
       | mina_jamshidian wrote:
       | Does Zerobox support audit logging for blocked network or file
       | operations?
        
         | afshinmeh wrote:
         | I added some basic --debug support earlier today, but I will
         | work on proper JSONL/Otel integration soon.
        
       ___________________________________________________________________
       (page generated 2026-04-01 23:00 UTC)