Show HN: Fence – Sandbox CLI commands with network/filesystem restrictions
78 points| jy-tan | 1 month ago |github.com
Fence wraps any command in a sandbox that blocks network by default and restricts filesystem writes. Useful for running semi-trusted code (package installs, build scripts, unfamiliar repos) with controlled side effects, or even just blocking tools that phone home.
> fence curl https://example.com # -> blocked
> fence -t code -- npm install # -> template with registries allowed
> fence -m -- npm install # -> monitor mode: see what gets blocked
One use-case is to use it with AI coding agents to reduce the risk of running agents with fewer interactive permission prompts:
> fence -t code -- claude --dangerously-skip-permissions
You can import existing Claude Code permissions with `fence import --claude`.
Fence uses OS-native sandboxing (macOS sandbox-exec, Linux bubblewrap) + local HTTP/SOCKS proxies for domain filtering.
Why I built this: I work on Tusk Drift, a system to record and replay real traffic as API tests (https://github.com/Use-Tusk/tusk-drift-cli). I needed a way to sandbox the service under test during replays to block localhost outbound connections (Postgres, Redis) and force the app to use mocks instead of real services. I quickly realized that this could be a general purpose tool that would also be useful as a permission manager across CLI agents.
Limitations: Not strong containment against malware. Proxy-based filtering requires programs to respect `HTTP_PROXY`.
Curious if others have run into similar needs, and happy to answer any questions!
uwemaurer|1 month ago
Currently it seems to allow read access by default and only allows to block some paths with with "denyRead"
jy-tan|1 month ago
The challenge is that most programs need read access to system paths (/lib, /usr, /etc, /proc) just to run. A pure "deny all reads" mode would require users to figure out every dependency, which might be painful.
That said, a middle-ground would be reasonable, perhaps something like "defaultDenyRead: true" that blocks home/cwd/etc but still allows essential system paths, then lets you opt-in with "allowRead".
Curious what is your use case that makes deny-by-default reads more helpful? Either way, will file this as an issue.
will_wright|1 month ago
https://github.com/anthropic-experimental/sandbox-runtime
mellosouls|1 month ago
https://github.com/Use-Tusk/fence?tab=readme-ov-file#attribu...
foresto|1 month ago
This could allow finer control than the application's own sandbox offers. For example, Flatpak apps run in bubblewrap containers with all-or-nothing network permissions. Being able to restrict access by domain name would be useful.
jy-tan|1 month ago
When you run `fence flatpak run <app>`, Fence creates a bwrap sandbox with its own user namespace, Flatpak then tries to create another user namespace inside, so you'd get something like `bwrap: setting up uid map: Permission denied`.
The outer sandbox doesn't grant the capability for nested namespace creation (otherwise it would defeat much of the security), so Fence can't wrap Flatpak (or similar namespace-based sandbox tools) in a useful way. Ideally you'd need something at the network level outside any sandbox.
That said, open to suggestions if anyone knows of a feasible solution.
whinvik|1 month ago
I got tired of setting individual allow lists for each CLI, hopefully now I can run them all in Yolo mode while fence does the centralized sandboxing.
jy-tan|1 month ago
_pktm_|1 month ago
jy-tan|1 month ago
Fence handles well supply-chain scripts that phone home, tools that write broadly across your filesystem, accidental secret leakage, the "opportunistic" stuff that makes up most real-world supply chain incidents.
I hedge on malware because: (1) Domain filtering relies on programs respecting HTTP_PROXY, and malware could ignore it (though direct connections are blocked at the OS level, so they'd fail rather than succeed), (2) OS sandboxes (sandbox-exec, bubblewrap) aren't VM-level isolation and I believe determined attackers could exploit kernel bugs, (3) there are no resource limits or content inspection.
The threat model is really "reduce blast radius from code you're running anyway". For a stronger containment boundary you'd want a proper VM.
More thoughts in the security model doc (https://github.com/Use-Tusk/fence/blob/main/docs/security-mo...) if you're curious!
Marceltan|1 month ago
vivzkestrel|1 month ago
jy-tan|1 month ago
``` fence -t code pip install requests fence -t code npm install express ```
This restricts writes to workspace + cache dirs, blocks reading credentials, limits network to allowlisted domains, and blocks dangerous commands (`rm -rf`, `npm publish`, etc).
luckman212|1 month ago
netcoyote|1 month ago
- https://github.com/webcoyote/clodpod: sandboxes AI agents in a MacOS virtual machine
Note: I’m the author of both of these Apache open-source projects
jy-tan|1 month ago
gregpr07|1 month ago
kxbnb|1 month ago
We're working on similar containment problems but at the API/MCP layer at keypost.ai - enforcing what outbound calls an agent can make rather than what local filesystem/network it can access. The two layers complement each other well.
The "restrictions as code" pattern is powerful. Are you thinking about extending to other resource types (API calls, token budgets, etc.)?
jy-tan|1 month ago
I think Fence should stay a thin wrapper around OS primitives (sandbox-exec, bubblewrap, Landlock), so not much beyond what it does today. The one extension that probably makes sense is basic resource limits (CPU, memory, fork bombs, etc). But API semantics and MCP tool restrictions belong in a different layer.