DEV Community

Paul Spread
Paul Spread

Posted on Originally published at agentbadge.xyz

Your API Process Should Not Hold the Money Key

One environment variable ran three different powers on our payment stack: it moved escrowed USDC on mainnet, it signed the verdicts that tell buyers an agent did the job, and it stamped operational attestations. One env dump, one debug endpoint, one RCE — and whoever leaked it owned all three at once.

The god key

ARC_EVALUATOR_KEY was three keys in one trench coat:

  • Money — evaluator authority on escrow settlements. Drains real funds.
  • Ops — attestations, anchor writes, venue evaluation calls.
  • Verdict — the signature behind every public verdict.

A /proc/<pid>/environ dump gets all three in one read.

The fix: split + socket

Three secrets replace one: ARC_SETTLE_KEY (money), ARC_OPS_KEY (ops writes), ARC_VERDICT_SIGNER_KEY (verdicts). The money key moves into a second process on the same host — a small Bun signer service that answers over a Unix socket file (NDJSON-RPC, no TCP, zero network surface).

# API child starts with the money key REMOVED from env:
exec env -u ARC_SETTLE_KEY -u SIGNER_KEY bun src/server/index.ts
Enter fullscreen mode Exit fullscreen mode

The API talks through an ArcSigner seam — same interface as the env backend, so callers can't tell which is wired. A policy layer allowlists target contracts and caps gas: even a compromised API can only request operator-approved signatures.

Fail fast, never fall back

Signer dead → 503 signer_unavailable before x402 payment runs — you can't be charged for a service that can't sign. Free routes keep serving. Operator gets a Discord/Telegram alert, throttled to one per 5 minutes. No silent fallback key — that would recreate the god-key.

Rotation without breakage

GET /keys/verdict-signers.json publishes {current, next} evaluator addresses — electron-builder's trust model. Verdicts are EIP-712 self-describing: recover the signer, compare to the embedded address. Retired-key verdicts verify forever.

Honest tradeoffs

  • Same-host RCE can still request signatures — policy bounds it, doesn't eliminate it.
  • Ops/verdict keys still live in env — money moved first; migration planned.
  • +1 process, ~$0 recurring.

When KMS/MPC

When volume makes self-hosting the risky option, or compliance requires non-exportable keys. AWS KMS, Web3Signer, Circle dev-controlled wallets (verified: ARC support + EIP-712) — the seam accepts all three without changing callers.

Check your own processes

tr '\0' '\n' < /proc/<pid>/environ | grep -iE 'key|secret'
Enter fullscreen mode Exit fullscreen mode

Whatever prints is what an RCE inherits.

Full article: https://agentbadge.xyz/blog/keyless-signer

Top comments (0)