Content
# ProxyCreds
**An ephemeral credential broker for LLM agents, exposed over MCP.**
[](https://deepwiki.com/ImAnonFR/ProxyCreds)
> Have questions about the codebase? Ask them on
> [DeepWiki](https://deepwiki.com/ImAnonFR/ProxyCreds) for AI-generated docs and
> answers about this repository.
Handing long-lived API keys to an LLM agent is a bad idea: keys end up in
transcripts, logs and model context, and once they leak they stay valid until
someone notices and rotates them by hand. ProxyCreds keeps the real
credentials in an encrypted vault and hands agents nothing but **opaque,
short-lived tokens** (`pcx_...`, 10-minute TTL by default). The real secret is
injected server-side, at the last possible moment:
- **API keys** — the agent calls an injection gateway (`/gw/<service>/...`)
that validates the token, enforces per-grant method/path policies, injects
the real key and forwards the request upstream.
- **Proxy credentials** (residential/datacenter proxies) — the agent points a
normal HTTP proxy client at the ProxyCreds relay; the relay authenticates the
ephemeral token and tunnels through the real upstream proxy.
- **SSH access** — the agent connects to the ProxyCreds bastion using its
token as the SSH password; the bastion opens the real session to the target
host with the real key/password and bridges it transparently.
If a token leaks it's usually already expired, it can be revoked in one click,
and it's useless anywhere except through ProxyCreds itself.
```
LLM agent ──MCP──> ProxyCreds ──> encrypted vault (real creds never leave)
│ │
│ pcx_token ├── policies (agent × service × scopes × TTL)
└──network──> gateway / relay / bastion ──real cred injected──> real API / proxy / host
└── audit log (every token event and request)
```
## Repository layout
| Path | Description |
|---|---|
| `backend/` | FastAPI control plane, injection gateway, proxy relay, SSH bastion, MCP server (Python 3.12) |
| `dashboard/` | Next.js admin dashboard (services, agents, policies, tokens, audit) |
| `docker-compose.yml` | Full stack: Postgres + backend + dashboard |
## Quick start (dev)
### Backend
```bash
cd backend
python -m venv .venv
.venv/Scripts/activate # Windows — use bin/activate on Unix
pip install -r requirements.txt
uvicorn proxycreds.main:app --reload --port 8000
```
In dev, everything you need is created on first run — you don't have to
generate anything by hand:
- the SQLite database (`backend/proxycreds.db`),
- the master key (`backend/.master_key`) used for envelope encryption,
- the SSH bastion host key (`backend/.bastion_host_key`).
The proxy relay (port 8080) and SSH bastion (port 2222) start automatically
alongside the API. All three generated files are git-ignored; for production
you provide your own master key instead (see below).
### Dashboard
```bash
cd dashboard
npm install
npm run dev
```
Open http://localhost:3000, create your organization, then:
1. **Services** — add a credential (e.g. a GitHub PAT with upstream base URL
`https://api.github.com` and format `Bearer {secret}`), an upstream proxy,
or an SSH target.
2. **Agents** — create an agent key (`pca_...`, shown once).
3. **Policies** — grant the agent access to a service with method/path scopes
and a TTL.
4. **Setup MCP** — copy the generated MCP config into your agent
(`.cursor/mcp.json`, Claude Desktop config, and so on).
### MCP server
```json
{
"mcpServers": {
"proxycreds": {
"command": "python",
"args": ["-m", "proxycreds.mcp_server"],
"env": {
"PYTHONPATH": "/path/to/ProxyCreds/backend",
"PROXYCREDS_API_URL": "http://localhost:8000",
"PROXYCREDS_AGENT_KEY": "pca_<your-agent-key>"
}
}
}
}
```
`PYTHONPATH` must point at the `backend` directory so the module resolves. On
Windows — or any setup with a virtualenv — set `command` to the venv Python
(e.g. `C:\...\backend\.venv\Scripts\python.exe`) so the dependencies are found.
Restart your agent after editing the config.
Tools exposed to the agent:
| Tool | Description |
|---|---|
| `list_services()` | Services this agent can reach (names and policies only, no secrets) |
| `request_access(service, reason)` | Get an ephemeral `pcx_` token plus usage instructions |
| `renew_token(token_id)` | Extend a token before it expires |
| `release_token(token_id)` | Revoke a token once you're done |
The agent then calls, for example, `GET http://localhost:8000/gw/github/user`
with `Authorization: Bearer pcx_...`, and the real PAT is injected server-side.
### Using it without MCP (direct API)
MCP is optional. The same flow works over a plain HTTP API, so humans, scripts
and CI can share scoped access without ever seeing the real credential. See
**[README_API.md](./README_API.md)** for the full agent-API reference, with
`curl`/Python examples for API, proxy and SSH services.
## Full stack (Docker)
The whole stack — Postgres, backend (API + gateway + relay + SSH bastion) and
dashboard — comes up with a single command:
```bash
docker compose up -d --build
```
Then open http://localhost:3000. Exposed ports:
| Port | Service |
|---|---|
| 3000 | Dashboard |
| 8000 | API + injection gateway |
| 8080 | Proxy relay |
| 2222 | SSH bastion |
On first boot the master key and the SSH bastion host key are generated
automatically and stored in a named volume (`pc_keys`), so they survive
container rebuilds. That's fine for trying it out or a single-host deployment.
For a real production setup, set your own master key so it doesn't live only
inside a Docker volume — losing it means losing every stored credential:
```bash
cp .env.example .env
# generate a key and paste it into .env as PC_MASTER_KEY:
python -c "import base64,secrets;print(base64.b64encode(secrets.token_bytes(32)).decode())"
# also set POSTGRES_PASSWORD, PC_*_PUBLIC_HOST / URL, then:
docker compose up -d --build
```
Put a TLS-terminating reverse proxy (Caddy, Traefik, nginx) in front for real
deployments and set `PC_GATEWAY_PUBLIC_URL`, `PC_RELAY_PUBLIC_HOST` and
`PC_SSH_BASTION_PUBLIC_HOST` accordingly.
## Security model
- **Envelope encryption** — master key → per-org DEK (AES-256-GCM) → credential
secrets. Secrets are decrypted in memory only at injection time and dropped
immediately afterwards.
- **Opaque tokens** — `pcx_` tokens are 256-bit random, stored hashed
(SHA-256), bound to an agent × service × grant, and TTL-capped (1h max).
- **Policies** — allowed HTTP methods and path globs per grant for APIs, and
destination host allow-lists for proxies; denied requests are audited.
- **SSRF guard** — upstreams that resolve to private, loopback or link-local
addresses are rejected, re-checked at request time to defend against DNS
rebinding.
- **Header scrubbing** — agent-supplied `Authorization`/`Cookie` headers are
stripped before forwarding; `Set-Cookie` and auth headers are stripped from
responses. The gateway can also redact the real secret if an upstream echoes
it back.
- **Kill switches** — revoke a single token, disable an agent (which revokes
all of its tokens), or disable a service.
- **Audit** — every token issuance, renewal, revocation, gateway request, relay
connection, SSH session and policy denial is logged, without secrets.
- **Multi-tenant** — all data is scoped by organization, with a separate
encryption key per org.
### Known limitations
- Request-signing schemes (AWS SigV4 and similar) can't be proxied
transparently; the plan is to support them through native ephemeral
credentials (STS) instead.
- Rate limiting is in-memory per process; move it to Redis for multi-replica
deployments.
## Tests
```bash
cd backend
python -m pytest tests -q
```
The suite covers vault write-only behavior, the token lifecycle
(issue/renew/release/revoke), gateway injection against a mocked upstream,
policy enforcement (methods and paths), the SSH bastion, audit logging, and
tenant isolation.