Security Model
zod-vault uses a zero-knowledge architecture. The server cannot read your data.
Threat Model
Section titled “Threat Model”Protected Against
Section titled “Protected Against”- Server compromise — Data is encrypted, server has no keys
- Database leaks — Only encrypted blobs stored
- Man-in-the-middle — HTTPS + client-side encryption
- Unauthorized access — JWT auth + user isolation
NOT Protected Against
Section titled “NOT Protected Against”- Client-side compromise — Malware on user’s device
- Recovery key theft — If someone has your key, they decrypt
- Weak recovery keys — Always use
generateRecoveryKey()
Encryption
Section titled “Encryption”Algorithm: AES-256-GCM
Section titled “Algorithm: AES-256-GCM”- 256-bit key size
- Authenticated encryption (integrity + confidentiality)
- NIST approved, widely audited
- Web Crypto API (native browser/Node.js)
Key Derivation: Argon2id
Section titled “Key Derivation: Argon2id”- Memory-hard (resistant to GPU/ASIC attacks)
- OWASP 2024 recommended parameters:
memory: 64 MBiterations: 3parallelism: 4hashLength: 32 bytesData Flow
Section titled “Data Flow”┌─────────────────────────────────────────────────┐│ CLIENT ││ ││ Recovery Key + Salt → Argon2id → AES Key ││ ↓ ││ Plaintext → AES-256-GCM → Encrypted Blob ││ │└────────────────────────┬────────────────────────┘ │ HTTPS ▼┌─────────────────────────────────────────────────┐│ SERVER ││ ││ Stores: { blob, salt, metadata } ││ Knows: NOTHING about your data ││ │└─────────────────────────────────────────────────┘What the Server Stores
Section titled “What the Server Stores”| Data | Encrypted? | Notes |
|---|---|---|
| User email | No | Needed for login |
| Password hash | Hashed | Argon2id |
| Vault data | Yes | Opaque blob |
| Vault salt | No | Useless without key |
| Timestamps | No | For sync |
What the Server Cannot Do
Section titled “What the Server Cannot Do”- Read vault contents
- Recover data without recovery key
- Decrypt even with database access
- Impersonate users
Authentication
Section titled “Authentication”JWT Tokens
Section titled “JWT Tokens”- Access token: 15 min expiry
- Refresh token: 7 day expiry
- Unique
jticlaim (no replay) - Refresh rotation
Password Hashing
Section titled “Password Hashing”Argon2idmemory: 64 MBiterations: 3parallelism: 4Passkeys (WebAuthn)
Section titled “Passkeys (WebAuthn)”- Hardware-backed
- Phishing-resistant
- Recommended over passwords
The crypto is ~300 lines of TypeScript:
git clone https://github.com/nicodlz/zod-vaultcat packages/crypto/src/*.ts | wc -lUses:
- Web Crypto API (native, no custom crypto)
hash-wasmfor Argon2id (audited WASM)
Reporting Vulnerabilities
Section titled “Reporting Vulnerabilities”Found an issue?
- Do not open a public issue
- Email: ndlz@pm.me
- Include: description, steps, impact
Response within 48 hours.