Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

sproxy (secure proxy)

Motivation

Do not send the secrets (API tokens, passwords) to LLM providers. If the secrets are in the conversation context, you can consider them compromised. So, don't let them ever enter the context. sproxy helps with this.

How it works?

At request time, sproxy detects the secrets placeholders and injects the real secrets to the outbound requests. The LLMs only see the placeholder values at all times.

             placeholder {{GITHUB_TOKEN}}                 real secret
   ┌────────┐  ───────────────────────►  ┌────────┐  ───────────────►   ┌──────────┐
   │  LLM   │                            │ sproxy │   leak scan +       │ approved │
   │ agent  │  ◄───────────────────────  │        │   audit             │  host    │
   └────────┘        response            └────────┘                     └──────────┘
                                              │
                                              ├─►  ✗ block leak to attacker domain
                                              └─►  🧾 .sproxy/audit.jsonl

Features

  • provides a list of placeholder env values to be used by the LLM
  • configure specific domains to which the secret should be ingested
  • monitor and audit all traffic originating from LLM
  • works with authorization Headers, Parameters and Postgres protocol
  • local-first and fully open-source
  • works with Codex, Claude Code and other harnesses

Prerequisites

sproxy uses mitmdump and will be pulled automatically by pip install:

pip install sproxy

If you prefer to install mitmproxy separately, use pip install --no-deps sproxy and make sure mitmdump is available on your PATH (or pass --mitmdump to sproxy run).

Quickstart

# 1. Write a starter policy and edit it.
sproxy init                        # creates ./sproxy.toml

# 2. Run your agent behind the guard.

# Start sproxy
sproxy run
# And load the placeholder Env variables
eval $(sproxy env) && codex

# Or run the process together with sproxy
sproxy run -- codex

# 3. After a session, check the audit log wasn't touched.
sproxy audit verify .sproxy/audit.jsonl

On first run, mitmproxy generates its CA at ~/.mitmproxy/mitmproxy-ca-cert.pem. sproxy points the agent's TLS trust env vars (NODE_EXTRA_CA_CERTS, REQUESTS_CA_BUNDLE, SSL_CERT_FILE, …) at that file automatically. Run sproxy ca to print the path.

To observe secret injection on your local machine, follow QUICKSTART.md.

Placeholder environment variables

When a secret name is a valid environment-variable name, sproxy also exports that name to the guarded process as an per-session secret placedholer starting with sproxy. For example, with a GITHUB_API_KEY secret, an SDK sees:

GITHUB_API_KEY=sproxy_v1_<random-session-handle>

sproxy replaces that handle with the real key only for the secret's allowed hosts. The handle is different for every sproxy run session and stops working when that session ends.

Secret backends supported:

  • gopass:PATH,
  • pass:PATH,
  • vault:PATH#FIELD (HashiCorp Vault, via the vault CLI's existing auth)
  • env:VAR
  • file:PATH
  • literal:VALUE

Config file

The policy is loaded from -c PATH config file if given, else ./sproxy.toml, else the user-level ~/.config/sproxy/sproxy.toml. Relative paths inside a policy (audit_log, sslrootcert, confdir) resolve against the config file's own directory.

Editing the policy while sproxy run hot-reloads sproxy. (Note that you might have to re-authorize loading the secrets).

PostgreSQL

The usual placeholder injection does not work for PostgreSQL like it does for http. SCRAM authentication proves knowledge of the password inside the client, so there is no request in flight to rewrite. Instead, each [postgres.NAME] profile becomes a local endpoint that terminates the wire protocol: the agent's client authenticates to sproxy with a per-session token. Sproxy opens the real connection to the host pinned in policy. The real password never enters the agent's environment, but it sees a fake placeholder which sproxy uses.

[postgres.develop]
host = "db.example.com"          # the real server
port = 5432
listen = 6432                    # local endpoint port; omit for auto-assigned
password_source = "gopass:work/postgres/develop/password"
user = "app_readonly"            # optional: default role
database = "appdb"               # optional: default database
sslmode = "verify-full"          # upstream TLS (default); "disable" only for local dev servers
sslrootcert = ""                 # CA bundle (e.g. the AWS RDS bundle); "" = system trust store

Each endpoint is advertised to the session through an environment variable named after the profile which will render after sproxy run or sproxy env.

The audit log

Stores one line per request captured. Example:

{"seq":1,"ts":"...","host":"attacker.com","method":"POST","decision":"blocked","rules":["secret:GITHUB_TOKEN"], ...}

TLS interception & certificate pinning

sproxy reads HTTPS by acting as a MITM with a trusted local CA. Clients that pin certificates (require a specific cert, not merely a valid one) will reject that CA and fail the handshake, and won't have their secrets replaced. Use passthrough_hosts to whitelist such hosts:

passthrough_hosts = ["api.vendor.com"]     # tunneled without interception

Commands

Command What it does
sproxy run [-c policy] [--port N] [--insecure] [--log-file path] [--no-reload] [-- <cmd…>] Run a command behind the guard; no command holds a session open. Policy edits apply live unless --no-reload
sproxy init [-c path] [--force] Write a starter policy
sproxy env Print exports that join this shell to the live session
sproxy ca [-c policy] Print the mitmproxy CA cert path
sproxy audit verify <log> Check the audit chain is intact
sproxy version Print version

License

MIT

About

Secure Proxy to Inject Secrets and Keep them out of Agents Contexts

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages