Security

How LEASH protects your keys

LEASH holds other people's production keys. This is the honest version of how it protects them, and where it stops.

The model

Agents are powerful and they make mistakes. Prompt rules ("never delete the database") live inside the model and can be ignored, forgotten or injected away. LEASH moves the rules outside the model:

  1. The agent never holds a real key. It holds an lsh_ token that only works through LEASH, only for one provider, only within its policy, and only until it expires or you revoke it.
  2. Irreversible calls are held. LEASH checks every call against a versioned map of operations that cannot be undone. Those wait for a human.
  3. Only a passkey can release a hold. Not the agent, not the CLI, not an API key.
  4. Everything is recorded in a hash-chained log you can verify.

How keys are protected

How approvals work

  1. Your agent makes an irreversible call. LEASH stops it and returns 428 held_for_approval with a link.
  2. You open the link (or the app) and see the exact method, host, path, the rule that matched, why, and a preview of the request itself: the SQL, the GraphQL or the body.
  3. You approve with your passkey: Face ID, Touch ID, Windows Hello or a security key. The check happens on your device; LEASH only verifies a signature.
  4. The approval covers that exact request, identified by a hash of its method, path and body, once, for ten minutes. A different request, or the same one twice, is held again.
The CLI can sign in, add keys and mint tokens, but it can never approve a hold or pre-approve irreversible operations. An agent on your laptop can read the CLI's files, so the CLI is treated as something the agent could control.

Controls, mapped to OWASP

AreaControlOWASP
Sign-inPasskeys only. User verification required, origin and RP ID checked, single-use five-minute challenges, signature counters.A07
Sessions__Host- cookie, HttpOnly, Secure, SameSite=Strict, 12 hours. CLI sessions are bearer tokens stored only as SHA-256 hashes.A07
CSRFWeb writes need the same Origin and an x-leash header. No CORS; preflight refused.A01
AuthorizationEvery query is scoped to your account. Other accounts' holds, tokens and keys return 404 (tested).A01, API1
Privilege separationCLI sessions cannot approve holds, pre-approve irreversible operations or delete the account.A01, A06
SecretsEnvelope encryption with row-bound authenticated data. No API returns a secret; secrets never logged.A04
InjectionParameterized SQL only. Bodies size-capped and parsed as JSON only.A05
SSRFFixed upstream host per provider, path checks, no redirects.A01, API7
AbuseRate limits per token (default 120 a minute), per account and per IP (salted hash, IPv6 by /64).API4
BrowserStrict CSP with Trusted Types, HSTS preload, COOP, CORP, frame-ancestors none, tight Permissions-Policy. No third-party scripts.A02
Supply chainZero runtime dependencies in the Worker and the CLI. CI actions pinned by commit SHA.A03, A08
LoggingAppend-only, hash-chained audit log with a verify endpoint. No bodies, tokens or keys in logs; a hold is logged with a hash of its preview.A09
AgentsExcessive agency is the threat LEASH exists for. Irreversible calls are held outside the model.LLM06

OWASP Top 10 2025 numbering. API = OWASP API Security Top 10, LLM = OWASP Top 10 for LLM Applications.

What LEASH does not protect against

Report a vulnerability

Email security@gautamkhosla.com. Please don't open a public issue. You'll hear back within 72 hours. Good-faith research is welcome; don't access other people's data or degrade the service.