DEV Community

Horizon Flow
Horizon Flow

Posted on

Your AI Agent's API Keys Are Probably in Plaintext Right Now

Every major AI agent framework stores API keys the same way: plaintext in a .env file or config YAML. OpenClaw, LangChain, AutoGPT, CrewAI — pick one. Your keys sit on disk, unencrypted, readable by any process, and one leaked log, bad plugin, or prompt injection away from exposure.

I built Vault-0 to fix this for my own OpenClaw agents. It's open source, runs locally, and never sends secrets anywhere.

The Core Problem

When you set up a ClawBot agent, the onboarding flow asks for your OpenAI key, Anthropic key, and whatever else your agent needs. Those get written to ~/.openclaw/.env. From that point on, they exist in plaintext on your disk indefinitely.

That means:

Any process running as your user can read them
A prompt injection that triggers a file-read tool can exfiltrate them
A verbose logging config can print them to stdout
A malicious MCP plugin can access them directly
This isn't theoretical. Agent frameworks are designed to give LLMs tool access. Tools read files. Files contain keys.

How Vault-0 Solves It
Secrets are encrypted in a local vault using AES-256-GCM with Argon2id key derivation. Your master passphrase (12+ characters) derives the encryption key. The vault file lives at ~/Library/Application Support/Vault0/vault.enc — it's unreadable without the passphrase.

When you launch your agent through Vault-0, the flow is:

Vault-0 decrypts your secrets in memory
Writes an ephemeral .env to ~/.openclaw/.env
Restarts the OpenClaw daemon so it reads the file
Waits ~2 seconds for the process to load
Zeros the .env (replaces contents with a comment)
Keys exist on disk for roughly 2 seconds. After that, the daemon has them in memory and the file is clean. The entire process runs in Rust.

Why Not a Vault API?
Tools like HashiCorp Vault or Doppler expect your application to call an API to fetch secrets at runtime. AI agent frameworks don't support this. They read .env at boot and that's it. You'd have to fork the framework to add vault integration.

The ephemeral .env approach works with the framework as-is. No upstream changes required.

Policy Engine
Vault-0 also runs a local proxy on 127.0.0.1:3840 that enforces security policies on outbound requests. Policies are YAML-based and support:

Domain allow/block lists — restrict which APIs your agent can call
HTTP method restrictions — block DELETE or PUT if your agent shouldn't modify resources
Output redaction — regex patterns that strip sensitive values from response bodies before they reach your agent
x402 spend caps — limit how much your agent can auto-pay per 402 settlement
Auto-settle rules — control whether 402 Payment Required responses are handled automatically
Example policy:

allow_domains:

  • api.openai.com
  • api.anthropic.com block_domains:
  • internal.corp.net output_redact_patterns:
  • "sk-[a-zA-Z0-9]{20,}" spend_cap_cents: 500 auto_settle_402: true MCP Hardening If your agent uses MCP (Model Context Protocol) tools, Vault-0 adds three protections:

Origin allowlist — only approved MCP server origins can be contacted
SSRF blocking — requests to private/internal IPs (127.x, 10.x, 192.168.x) are rejected
Token passthrough disabled — the proxy never forwards your client authorization tokens to MCP servers
MCP is powerful but it expands your agent's attack surface significantly. These controls reduce that surface without disabling MCP entirely.

Evidence Ledger
Every policy decision, proxied request, and payment event is logged to a SHA-256 chained evidence ledger. Each entry includes a timestamp, event type, detail string, and a hash of the previous entry — making the log tamper-evident.

You can export receipts from the dashboard and trace exactly what your agent did, when it did it, and which policy allowed or blocked it.

x402 Payment Support
Vault-0 includes native handling for the x402 payment protocol. When an upstream API returns HTTP 402 Payment Required:

Vault-0 parses the payment intent (amount, recipient, network)
Signs a payment authorization using EIP-3009 (TransferWithAuthorization) with your on-device EVM wallet
Retries the request with an X-PAYMENT header containing the signed payload
Logs the settlement to the evidence ledger
Your wallet's BIP-39 mnemonic is stored in macOS Keychain — it never leaves the Keychain and never touches the webview layer.

Tech Stack
Frontend: Tauri 2 + Svelte 4 + Tailwind CSS
Backend: Rust (Axum proxy, aes-gcm vault, argon2 KDF, alloy EVM signer)
Terminal: xterm.js + tauri-plugin-pty (embedded terminal for OpenClaw CLI)
Key storage: macOS Keychain via the keyring crate
Binary size: ~15MB. No Electron.
What's Not Done Yet
Being transparent about current limitations:

Spend tracking — the policy field for spend caps exists, but per-request cost tracking isn't implemented yet. Caps are only enforced at x402 auto-settlement time.
Wallet balance — get_wallet_balance() returns hardcoded zeros. No RPC calls to fetch real on-chain USDC balance yet.
Payment history — get_payment_history() returns an empty list. Pending payments are tracked but historical records aren't persisted.
Platform support — macOS only for v1.0. Keychain integration requires macOS 12+.
Agent frameworks — only OpenClaw is supported. The ephemeral .env pattern could work for other frameworks but the detection/migration flow is OpenClaw-specific.
Getting Started
git clone https://github.com/0-Vault/Vault-0.git
cd Vault-0
npm install
cargo tauri dev
The guided setup will detect your OpenClaw installation, scan for plaintext keys, and walk you through migrating them into the encrypted vault.

Links
Repo: github.com/0-Vault/Vault-0
Demo video: x.com/HorizonFlowLive/status/2021542413177909481

If you're running AI agents with API keys in plaintext .env files, give it a try. Issues and PRs welcome.

Top comments (0)