# What if my keys are stolen?

Keychains is built for a world where credentials can and will be compromised. Here's how every layer is protected — and what happens when things go wrong.

## Core design principle

**Authority lives server-side.** Tokens are short-lived pointers to server state. Stealing a token gives you minutes of access at most. Stealing a key triggers automatic detection. Every sensitive operation is gated by stateful server checks — never by the token alone.

## Threat scenarios

### Permission Token stolen

**Impact**  
Attacker can make proxied API calls for the token's remaining lifetime (5-15 minutes max). No ability to create new tokens or change scopes.

**Mitigation**  
Short TTL (5-15 min) means the window is tiny. Revoke the permission from the dashboard to invalidate instantly — all future minted tokens will fail version check. Audit log shows anomalous usage.

### Delegate ID stolen (without private key)

**Impact**  
None. The delegate ID alone cannot do anything — all operations require a cryptographic challenge-response with the private key.

**Mitigation**  
No action needed. The delegate ID is safe to log and reference.

### Delegate private key stolen

**Impact**  
Attacker can mint short-lived permission tokens and make proxied API calls within the delegate's scope until TTL expires.

**Mitigation**  
Revoke the delegate immediately from the dashboard or CLI. Use short TTLs (1-4 hours). The delegate cannot escalate beyond its scoped permissions.

### Machine SSH private key stolen

**Impact**  
Attacker could potentially authenticate as your machine and mint permission tokens.

**Mitigation**  
Keychains uses rolling challenges — each auth attempt must sign a server-issued nonce. If an attacker and the real machine both try to auth, the challenge desynchronizes. The server automatically detects this and triggers revalidation, locking out both until the user manually re-approves. The key rotation command generates a new keypair.

### Replay attack

**Impact**  
N/A — replayed tokens and signatures are rejected.

**Mitigation**  
Rolling challenges (nonces are single-use), short-lived JWTs (can't be reused after expiry), and stateful version tracking (version must match current server state).

### Parent permission revoked

**Impact**  
All delegates immediately become invalid. No orphaned access.

**Mitigation**  
Cascade revocation is automatic. The proxy validates the full chain (permission → delegate → token) on every request.

## What to do if compromised

1. **Revoke immediately**  
Go to the dashboard → Machines → Revoke. Or use the CLI: keychains permissions rm <id>. Takes effect in milliseconds.

2. **Rotate your keys**  
Run keychains machine rotate-keys to generate a new SSH keypair. The old public key is invalidated server-side.

3. **Check the audit log**  
Review the audit log to see what the attacker accessed. Every proxied call is logged with timestamp, endpoint, IP, and response status.

4. **Re-approve permissions**  
After rotation, your permissions will be in 'needs_revalidation' status. Approve them again from the dashboard to restore access.

**Tip:** The rolling challenge system means that **stolen SSH keys are automatically detected** on first use by the attacker. As soon as the real machine and the attacker make concurrent auth attempts, the server detects desynchronization and locks the machine for revalidation.

## Defense in depth

### Layer 1 — Identity
- Ed25519 SSH keypairs
- Rolling challenge nonces
- Hardware fingerprinting

### Layer 2 — Authorization
- Stateful server-side permissions
- User-approved scopes
- Version tracking

### Layer 3 — Execution
- 5-15 min token TTLs
- Scopes resolved at proxy time
- No secrets in tokens

### Layer 4 — Observability
- Full audit log
- Real-time dashboard
- Instant revocation

[Pre-approved Tokens](/content/docs/permissions/index.html) [Architecture](/content/docs/architecture/index.html)
