21 comments

[ 0.17 ms ] story [ 48.0 ms ] thread
[flagged]
It could even hash individual keys and scan context locally before sending to check if it accidentally contains them.
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.
> a secrets store that the model can "use" but never "read".

How would that work? If the AI can use it, it can read it. E.g:

    secret-store "foo" > file
    cat file
You'd have to be very specific about how the secret can be used in order for the AI to not be able to figure out what it is. You could provide a http proxy in the sandbox that injects a HTTP header to include the secret, when the secret is for accessing a website for example, and tell the AI to use that proxy. But you'd also have to scope down which URLs the proxy can access with that secret otherwise it could just visit a page like this to read back the headers that were sent:

https://www.whatismybrowser.com/detect/what-http-headers-is-...

Basically, for every "use" of a secret, you'd have to write a dedicated application which performs that task in a secure manner. It's not just the case of adding a special secret store.

This seems like an under-rated comment. You are right, this is a vulnerability and the blog doesn't talk about this.
Sounds like an attacker could hack Anthropic and get access to a bunch of companies via the credentials Claude Code ingested?
I guess I don't understand why anyone thinks giving an LLM access to credentials is a good idea in the first place? It's been demonstrated best practice to separate authentication/authorization from the LLM's context window/ability to influence for several years now.

We spent the last 50 years of computer security getting to a point where we keep sensitive credentials out of the hands of humans. I guess now we have to take the next 50 years to learn the lesson that we should keep those same credentials out of the hands of LLMs as well?

I'll be sitting on the sideline eating popcorn in that case.

While sandboxing is definitely more secure... Why not put a global deny on .env-like filename patterns as a first measure?
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

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
Isn’t this (part of) the point of MCP.
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?

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

> With macaroons you can design the authz scheme that you want for any arbitrary API.

How would you build such an authz scheme? When claude asks permissions to access a new endpoint, if the user allows it, then reissue the macaroons?

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.
I’ve been using 1Password’s env templates with `op run` for this locally. It hijacks stdout and filters your credentials.

That does not make it immune to Claude’s prying, but at least Claude can then read the .env file and satisfy its need to prove that a credential exists without reading it.

I have found even when I say a credential exists and is correct Claude does not believe me. Which is infuriating. I’m willing to bet Claude’s logs have a gold mine that could own 90% of big tech firms.

A proxy is a good solution although a bit more involved. A great first step is just getting any secrets - both the ones the AI actually needs access to and your application secrets - out of plaintext .env files.

A great way to do that is either encrypting them or pulling them declaratively from a secure backend (1Pass, AWS Secrets Manager, etc). Additional protection is making sure that those secrets don't leak, either in outgoing server responses, or in logs.

https://varlock.dev (open source!) can help with the secure injection, log redaction, and provide a ton more tooling to simplify how you deal with config and secrets.

"When hostnames and headers are hard to edit: mitmproy add-ons"

"The mitmproxy tool also supports addons where you can transform HTTP requests between Claude Code and third-party web servers. For example, you could write an add-on that intercepts https://api.anthropic.com and updates the X-API-Key header with an actual Anthropic API Key."

"You can then pass this add-on via mitmproxy -s reroute_hosts.py."

If using HAproxy, then is no need to write "add-ons", just edit the configuration file and reload

For example, something like

   http-request set-header x-api-key API_KEY if { hdr(host) api.anthropic.com }

   echo reload|socat stdio unix:/path-to-socket/socket-name
For me, HAproxy is smaller and faster than mitmproxy