Threat Model
| Threat | Mitigation |
|---|---|
| D1 database dump/leak | Secret values and keys are AES-256-GCM encrypted. API keys are hashed. |
| API key theft | Keys are scoped. System keys only access specific project:environment pairs. |
| Network interception | All traffic is TLS-encrypted (HTTPS enforced by Cloudflare). |
| Master key compromise | Single point of failure by design. See Master Key Management. |
| Brute-force key guessing | API keys are 256-bit random. Keyspace is 2^256 — infeasible. |
| Insider threat (DB admin) | Encrypted data is unreadable without master key (Worker secret). |
Security Boundaries
Key principle: Plaintext secrets exist ONLY in Worker memory during request processing. Never logged, never cached.What Gets Encrypted
Encrypted (AES-256-GCM)
- Secret values (
DB_PASSWORD=hunter2) - Secret key names (
DB_PASSWORD) - API key labels
- System key scope definitions
NOT Encrypted (by design)
- Row IDs (UUIDs — no information leakage)
- Timestamps (created_at, updated_at)
- Project names
- Environment names
- API key type (
user/system) - API key permission level
- Revocation status
API Key Security
Key Format
Key Storage
Why SHA-256 and not Argon2id? API keys have 128 bits of entropy (vs ~40 bits for passwords), making brute-force infeasible regardless of hash speed. SHA-256 is fast, native, and adds zero dependencies.
Permission Levels
| Read | Write | Manage Projects | Manage Keys | |
|---|---|---|---|---|
| User key | ✅ | ✅ | ✅ | ✅ |
System key — read | ✅ (scoped) | ❌ | ❌ | ❌ |
System key — readwrite | ✅ (scoped) | ✅ (scoped) | ❌ | ❌ |
Master Key Management
Single Point of Failure
The master key is the single root of trust. If lost, all encrypted data is permanently unrecoverable. There is no backdoor.Mitigations
- Managed by Cloudflare — Stored as Worker secret, encrypted at rest
- User backup required — Must save key in password manager or physical safe
- Clear warnings —
kfl initprompts to confirm key was saved
Master Key Format
| Property | Requirement |
|---|---|
| Encoding | Standard base64 (RFC 4648) |
| Length | 44 characters (with padding) |
| Decoded size | Exactly 32 bytes |
| Entropy | 256 bits |
Generation
kfl init generate one automatically.
Update Behavior
When runningkfl init on an existing deployment:
- Master key is NEVER changed — even if
--master-keyis provided - This prevents catastrophic data loss from accidental key rotation
Next Steps
Encryption Details
Deep dive into the crypto implementation.
API Keys
Learn how to create and manage API keys.
