OpenShell is the gem here indeed. A lot of good ideas like network sandbox that does TLS decryption and use of policy engine to set the rules. However:
> Credentials never leak into the sandbox filesystem; they are injected as environment variables at runtime.
The LLM will easily leak these credentials out. So the creds should be outside the sandbox, and the only thing the sandbox should see is a connection API that opens a socket/file handle.
Alternatively where is needs an API key, it should be one bound to the endpoint using it. E.g. a ticket granting ticket is used to create a bound ticket.
A copy on write filesystem would be an interesting way to sandbox writes, but there is difficulty in checking the diff.
1) Not all systems respect HTTP_PROXY. Node in particular is very uncooperative in this regard.
2) AWS access keys can’t be handled by simple credential swap; the requests need to be resigned with the real keys. Replicating the SigV4 and SigV4A exactly was bit of a pain.
3) To be secure, this system needs to run outside of the execution sandbox so that the agent can’t just read the keys from the proxy process.
For Airut I settled on a transparent (mitm)proxy, running in a separate container, and injecting proxy cert to the cert store in the container where the agent runs. This solved 1 and 3.
Great tool. Yours is much more sophisticated than mine, but I also came up with a similar solution to my personal problem of running opencode web in a container with access to all my API keys. I also settled on mitmproxy. Before I was trying to use IPTables, but that didnt really safely work, because the agent could still escape if he tried hard enough.
I'm happy there is some work being done of securing agents more properly. Maybe this helps broader adoption for experiments with access to more services.
Im literally working on the exact same solution. Difference is I'm running the system in a Kubernetes cluster.
I essentially run a sidecar container that sets up ip tables that redirect all requests through my mitm proxy. This was specifically required because of Node not respecting HTTP_PROXY.
Also had to inject a self signed cert to ensure SSL could be proxied and terminated by the mitm proxy, which then injects the secrets, and forwards the request on.
Have you run into any issues with this setup? I'm trying to figure out if there's anything I'm missing that might come back to bite me?
I’ve been running this with workloads accessing Anthropic, GitHub, Gemini, and AWS & CF R2 APIs for a while now, and have not ran into issues. I’m sure there’s an API out there that won’t work out of the box but I’m positive that support could be added.
Another thing I did was to allow configuring which hosts each credential is scoped to. Replacement /resigning doesn’t happen unless host matches. That way it is not possible to leak keys by making requests to malicious hosts.
The last note about configuring hosts to credentials is an excellent idea, and one I did not think to do. Currently I'm just doing a replace on any that matches in the request.
This adds an extra layer of security to it. Much appreciated.
Also doesn't this mean I have to reconfigure all my tools to use HTTP and then when I forget to enable this it will fall back to getting MITM'd by the Internet? Fails open in the most insecure method ever
Alternative, and more robust approach is to give the agent surrogate credentials and replace them on the way out in a proxy. If proxy runs in an environment to which agent has no access to, the real secrets are not available to it directly; it can only make requests to scoped hosts with those.
I’ve built this in Airut and so far seems to handle all the common cases (GitHub, Anthropic / Google API keys, and even AWS, which requires slightly more work due to the request signing approach). Described in more detail here: https://github.com/airutorg/airut/blob/main/doc/network-sand...
OP isn't talking about giving agents credentials, that's a whole nother can of worms. And yes, agreed, don't do it. Some kind of additional layer is crucial.
Personally I don't like the proxy / MITM approach for that, because you're adding an additional layer of surface area for problems to arise and attacks to occur. That code has to be written and maintained somewhere, and then you're back to the original problem.
Yep - requires the client to trust the SSL cert of the proxy. Cooperative clients that support eg HTTP_PROXY may be easier to support, but for Airut I went for full transparent mitmproxy. All DNS A requests resolve to the proxy IP and proxy cert is injected to the container where Claude Code runs as trusted CA. As a bonus this closes DNS as potential exfiltration channel.
This is cool! Solving the same problem (authority delegation to resources like Github and Gmail) but in a slightly different way at https://agentblocks.ai
Container isolation is a good foundation, but one layer worth adding is network sandboxing. A filesystem-sandboxed agent can still exfiltrate data over the network if it gets prompt-injected — domain allowlists and egress filtering can reduce the risk significantly.
Another useful primitive is surrogate credentials: the agent never handles real API keys or tokens. A proxy swaps in real values only for scoped hosts on the way out. This keeps the access the agent has locked inside the container; surrogate credentials are not valid outside.
As someone with first-hand experience in implementing pass-through AR, I found the review well-made (e.g., they measured photon-to-photon latency) and extremely interesting. Here's a few observations I made:
1. 30 Hz frame rate and 50ms photon-to-photon latency sound so bad that I'm surprised they launched this at all. I would be very interested in trying this out to see how (un)comfortable the experience is. What I would have expected is pass-through feed rate synchronized to display frame rate (i.e., 90 Hz) and photon-to-photon latency no more than perhaps 2 frames (22ms). At 90 Hz and 11ms you can actually play ping-pong while wearing a pass-through headset.
2. I can relate with the exposure, saturation, and noise issues. The existing well-tuned video ISP pipes aren't suitable for low latency, and building a new one that achieves low latency and gives a good picture in indoor lighting from an essentially smartphone sensor with exposure time < 11ms and doesn't add multi-frame latency is HARD.
3. Above points to one possible explanation for the 30Hz capture; maybe they used a cheap sensor that can't produce usable picture in < 11ms exposure time (in dimly lit indoor environment) and thus had to go with 30Hz capture. Would be interesting to repeat the experiment in well-lit (outdoor) environment to see if the capture pipe kicks into a higher framerate.
4. I wonder if they do any warping to correct for the camera positions and how well that works. For AR-focused headset the ideal pass-through camera positions would approximate eye positions to minimize need for distortion. Even shifting capture positions a few centimeters forward from the eyes (which you'd need to do if you don't replace eyes with cameras or play tricks with optics) creates a subtle but noticeable effect unless corrected.
> Credentials never leak into the sandbox filesystem; they are injected as environment variables at runtime.
If anyone from the team is reading - you should copy surrogate credentials approach from here to secure the credentials further: https://github.com/airutorg/airut/blob/main/doc/network-sand...
reply