| ▲ | Using proxies to hide secrets from Claude Code(joinformal.com) |
| 71 points by drewgregory 6 days ago | 24 comments |
| |
|
| ▲ | dtkav 4 hours ago | parent | next [-] |
| I'm working on something similar called agent-creds [0]. I'm using Envoy as the transparent (MITM) proxy and macaroons for credentials. The idea is that you can arbitrarily scope down credentials with macaroons, both in terms of scope (only certain endpoints) and time. This really limits the damage that an agent can do, but also means that if your credentials are leaked they are already expired within a few minutes. With macaroons you can design the authz scheme that *you* want for any arbitrary API. I'm also working on a fuse filesystem to mount inside of the container that mints the tokens client-side with short expiry times. https://github.com/dtkav/agent-creds |
|
| ▲ | samlinnfer 6 hours ago | parent | prev | next [-] |
| Here's the set up I use on Linux: The idea is to completely sandbox the program, and allow only access to specific bind mounted folders. But we also want to have to the frills of using GUI programs, audio, and network access. runc (https://github.com/opencontainers/runc) allows us to do exactly this. My config sets up a container with folders bind mounted from the host. The only difficult part is setting up a transparent network proxy so that all the programs that need internet just work. Container has a process namespace, network namespace, etc and has no access to host except through the bind mounted folders.
Network is provided via a domain socket inside a bind mounted folder. GUI programs work by passing through a Wayland socket in a folder and setting environmental variables. The set up looks like this * config.json - runc config
* run.sh - runs runc and the proxy server
* rootfs/ - runc rootfs (created by exporting a docker container) `mkdir rootfs && docker export $(docker create archlinux:multilib-devel) | tar -C rootfs -xvf -`
* net/ - folder that is bind mounted into the container for networking
Inside the container (inside rootfs/root): * net-conf.sh - transparent proxy setup
* nft.conf - transparent proxy nft config
* start.sh - run as a user account
Clone-able repo with the files: https://github.com/dogestreet/dev-container |
| |
| ▲ | ekidd 4 hours ago | parent | next [-] | | I have a version of this without the GUI, but with shared mounts and user ID mapping. It uses systemd-nspawn, and it's great. In retrospect, agent permission models are unbelievably silly. Just give the poor agents their own user accounts, credentials, and branch protection, like you would for a short-term consultant. | | |
| ▲ | samlinnfer 4 hours ago | parent [-] | | The other reason to sandbox is to reduce damage if another NPM supply chain attack drops. User accounts should solve the problem, but they are just too coarse grained and fiddly especially when you have path hierarchies. I'd hate to have another dependency on systemd, hence runc only. |
| |
| ▲ | brunoborges 6 hours ago | parent | prev | next [-] | | Any particular reason why you shared these files in a gist rather a repo? | | | |
| ▲ | idorosen 6 hours ago | parent | prev [-] | | try firejail insread | | |
| ▲ | samlinnfer 5 hours ago | parent [-] | | Not even close to the same thing, with this setup you can install dev tools, databases, etc and run inside the container. It's a full development environment in a folder. |
|
|
|
| ▲ | jackfranklyn 6 days ago | parent | prev | next [-] |
| The proxy pattern here is clever - essentially treating the LLM context window as an untrusted execution environment and doing credential injection at a layer it can't touch. One thing I've noticed building with Claude Code is that it's pretty aggressive about reading .env files and config when it has access. The proxy approach sidesteps that entirely since there's nothing sensitive to find in the first place. Wonder if the Anthropic team has considered building something like this into the sandbox itself - a secrets store that the model can "use" but never "read". |
| |
| ▲ | JoshuaDavid 3 hours ago | parent | next [-] | | That's how they did "build an AI app" back when the claude.ai coding tool was javascript running in a web worker on the client machine. | |
| ▲ | iterateoften 6 hours ago | parent | prev [-] | | It could even hash individual keys and scan context locally before sending to check if it accidentally contains them. |
|
|
| ▲ | dang 7 hours ago | parent | prev | next [-] |
| Recent and related: https://news.ycombinator.com/item?id=46623126 via Ask HN: How do you safely give LLMs SSH/DB access? - https://news.ycombinator.com/item?id=46620990. |
|
| ▲ | TheRoque 6 hours ago | parent | prev | next [-] |
| At the moment I'm just using "sops" [1]. I have my env var files encrypted uth AGE encryption. Then I run whatever I want to run with "sops exec-env ...", it's basically forwarding the secrets to your program. I like it because it's pretty easy to use, however it's not fool-proof: if the editor which you use for editing the env vars is crashing or killed suddently, it will leave a "temp" file with the decrypted vars on your computer. Also, if this same editor has AI features in it, it may read the decrypted vars anyways. - [1]: https://github.com/getsops/sops |
| |
| ▲ | jclarkcom 6 hours ago | parent [-] | | I do something similar but this only protects secrets at rest. If you app has an exploit an attack could just export all your secrets to a file. I prototyped a solution where I use an external debugger to monitor my app, when the app needs a secret it generates a breakpoint and the debugger catches it and then inspects the call stack of the function requesting the secret and then copies it into the process memory (intended to be erased immediately after use). Not 100% security but a big improvement and a bit more flexible and auditable compared to a proxy | | |
|
|
| ▲ | JimDabell 4 hours ago | parent | prev | next [-] |
| Is this a reimplementation of Fly.io’s Tokenizer? How does it compare? https://fly.io/blog/tokenized-tokens/ https://github.com/superfly/tokenizer |
| |
| ▲ | dtkav 3 hours ago | parent | next [-] | | IMHO there are a couple axis that are interesting in this space. 1. What do the tokens look like that you are you storing in the client? This could just be the secret (but encrypted), or you could design a whole granular authz system. It seems like tokenizer is the former and Formal is the latter. I think macaroons are an interesting choice here. 2. Is the MITM proxy transparent? Node, curl, etc allow you to specify a proxy as an environment variable, but if you're willing to mess with the certificate store than you can run arbitrary unmodified code. It seems like both Tokenizer and Formal are explicit proxies. 3. What proxy are you using, and where does it run? Depending on the authz scheme/token format you could run the proxy centrally, or locally as a "sidecar" for your dev container/sandbox. | |
| ▲ | eddythompson80 4 hours ago | parent | prev [-] | | We truly are living in the dumbest timeline aren’t we. I was just having an argument with a high level manager 2 weeks ago about how we already have an outbound proxy that does this, but he insisted that a mitm proxy is not the same as fly.io “tokenizer”. See, that one tokanizes every request, ours just sets the Authorization header for service X. I tried to explain that it’s all mitm proxies altering the request, just for him to say “I don’t care about altering the request, we shouldn’t alter the request. We just need to tokenize the connection itself” |
|
|
| ▲ | josegonzalez 4 hours ago | parent | prev | next [-] |
| I am gonna be that guy and say it would be nice to share the actual code vs using images to display what the code looks like. It's not great for screenreaders and anyone who want to quickly try out the functionality. |
|
| ▲ | paulddraper 5 hours ago | parent | prev | next [-] |
| Isn’t this (part of) the point of MCP. |
| |
| ▲ | eddythompson80 3 hours ago | parent [-] | | Possibly, but the point is that MCP is a DOA idea. An agent, like Claude code or opencode, don’t need an MCP. it’s nonsensical to expect or need an MCP before someone can call you. There is no `git` MCP either . Opencode is fully capable of running `git add .` or `aws ec2 terminate-instance …` or `curl -XPOST https://…` Why do we need the MCP? The problem now is that someone can do a prompt injection to tell it to send all your ~/.was/credentials to a random endpoint. So let’s just have a dummy value there, and inject the actual value in a transparent outbound proxy that the agent doesn’t have access to. |
|
|
| ▲ | keepamovin 5 hours ago | parent | prev [-] |
| I think people's focus on the threat model from AI corps is wrong. They are not going to "steal your precious SSH/cloud/git credentials" so they can secretly poke through your secret-sauce, botnet your servers or piggy back off your infrastructure, lol of lols. Similarly the possibility of this happening from MCP tool integrations is overblown. This dangerous misinterpretation of the actual possible threats simply better conceals real risks. What might those real risks be? That is the question. Might they include more subtle forms of nastiness, if anything at all? I'm of the belief that there will be no nastiness, not really. But if you believe they will be nasty, it at least pays to be rational about the ways in which that might occur, no? |
| |
| ▲ | simonw 4 hours ago | parent | next [-] | | The risk isn't from the AI labs. It's from malicious attackers who sneak instructions to coding agents that cause them to steal your data, including your environment variable secrets - or cause them to perform destructive or otherwise harmful actions using the permissions that you've granted to them. | |
| ▲ | hobs 4 hours ago | parent | prev [-] | | Putting your secrets in any logs is how you get those secrets accidentally or purposefully read by someone you do not want to read it, it doesn't have to be the initial corp, they just need to have bad security or data management for it to leak online or have someone with a lower level of access pivot via logs. Now multiply that by every SaaS provider you give your plain text credentials in. |
|