Security
Himayah's threat model, the attacks it defends against, and the cryptographic decisions behind every default.
Security
Security is not an afterthought in Himayah — it's a design constraint. This page documents the threat model, every attack vector that was audited, and exactly how each one is mitigated in the codebase.
All mitigations described below are on by default. You don't need to enable any security feature manually.
Threat Model Summary
| # | Threat | Status |
|---|---|---|
| 1 | Timing side-channels on token comparison | ✅ Mitigated |
| 2 | Multi-node rate limit bypass | ✅ Mitigated |
| 3 | Host header spoofing on OAuth callbacks | ✅ Mitigated |
| 4 | Stateless session replay after sign-out | ✅ Mitigated |
| 5 | Offline dictionary attacks on password hashes | ✅ Mitigated |
| 6 | Cross-Site Request Forgery (CSRF) | ✅ Mitigated |
| 7 | PKCE downgrade on OAuth flows | ✅ Mitigated |
| 8 | XSS session token theft | ✅ Mitigated |
1. Timing Side-Channel on Token Comparison
Risk level: HIGH
Standard JavaScript === string equality short-circuits on the first mismatched byte. On a network-accessible endpoint, an attacker can measure the sub-millisecond response time difference and brute-force CSRF tokens, OAuth state parameters, or OTP codes one character at a time — without triggering rate limits.
Mitigation:
All security-critical comparisons in Himayah use a custom timingSafeEqual that always runs for the full string length regardless of where the mismatch occurs:
Applied to:
- CSRF token header vs cookie comparison
- OAuth
stateparameter verification - Magic link and OTP token verification
- Password hash comparison (after PBKDF2 derivation)
2. Multi-Node Rate Limit Bypass
Risk level: HIGH (for production serverless / multi-container deployments)
In-memory rate limiters are isolated to a single process. In a serverless environment (Vercel, Cloudflare Workers) or a load-balanced cluster, each instance maintains its own counter. A motivated attacker can exhaust OTP retries across N nodes, effectively multiplying the limit by N.
Mitigation:
Himayah makes the rate limiter pluggable. In-memory is the default (suitable for local dev), but production deployments should use:
- Redis:
@himayah/rate-limit-redis— shared atomic counters with TTL precision viaSET ... PX. Works with ioredis, node-redis, and Upstash. - Database:
DatabaseRateLimitStorefrom@himayah/core— stores counters in your existing DB. Zero extra infrastructure.
See the Rate Limiting guide for setup instructions.
Never use in-memory rate limiting in a multi-instance production deployment. Set rateLimitStore in your createAuth config.
3. Host Header Spoofing
Risk level: MEDIUM
In proxy-heavy environments (Cloudflare, Nginx, AWS ALB), the Host and X-Forwarded-Host request headers can be controlled by an attacker. If an auth library constructs OAuth redirect URIs or magic link URLs dynamically from these headers, an attacker can inject a malicious origin and capture auth codes or tokens.
Example attack:
Mitigation:
createAuth accepts an explicit baseUrl:
All OAuth callback URLs and magic link verification URLs are hardcoded to this baseUrl — never derived from request headers. This completely neutralizes host header injection attacks.
Always set baseUrl to your app's canonical URL from an environment variable. Never derive it from request.headers.get("host").
4. Session Replay After Sign-Out
Risk level: MEDIUM
Stateless JWE sessions are cryptographically self-contained. If a user's session cookie is stolen (e.g., via a physical compromise or log exposure), deleting the database session row does not invalidate the cookie — it remains valid until its exp claim expires.
Mitigation:
Himayah provides an opt-in stateful session store:
With this enabled:
- Every
auth.getSession(req)call validates the session ID against thesessionstable auth.signOut(req)deletes the database row — the session is immediately dead, even if the cookie is still present- Account bans, forced sign-outs, and password-change revocations all work reliably
When to use stateful sessions:
| Scenario | Recommendation |
|---|---|
| Standard SaaS app | Stateful sessions (safer, one extra DB query per request) |
| High-throughput API / Edge | Stateless JWE (faster, no DB lookup) |
| Requires immediate revocation | Must use stateful sessions |
5. Password Hashing
Risk level: HIGH (if using weak parameters)
Passwords stored as plain hashes (MD5, SHA-1, even SHA-256) are trivially crackable with GPU-accelerated dictionary attacks on modern hardware.
Mitigation:
The @himayah/plugin-password uses PBKDF2-SHA256 via the Web Crypto API with the following parameters:
- A unique 16-byte random salt is generated per password — rainbow table attacks are impossible
- 100,000 iterations makes each hash take ~100ms on modern hardware, making offline brute-force impractical
- The final hash is stored as
<salt>:<hash>in yourpasswordstable — Himayah never stores plaintext
PBKDF2 runs natively through crypto.subtle.deriveBits — no native addons, no Node.js-specific APIs. It works on every runtime Himayah supports.
6. Cross-Site Request Forgery (CSRF)
Risk level: HIGH
Without CSRF protection, an attacker can trick a logged-in user into submitting a form to your auth endpoints from a third-party origin (e.g., causing an unwanted password change or account modification).
Mitigation: Double-Submit Cookie Pattern
Himayah uses the double-submit cookie strategy:
- On first request, Himayah sets a
himayah.csrfcookie with a cryptographically random token (notHttpOnly— the JS client must read it) - All mutating requests (
POST,PUT,DELETE,PATCH) must include this token in thex-csrf-tokenheader - Himayah compares the cookie value and header value using
timingSafeEqual - Cross-origin requests cannot read cookies from a different origin — so an attacker cannot replicate the header
CSRF protection is enabled by default (csrf: true). The @himayah/client handles token extraction and injection automatically on every request.
7. OAuth PKCE Downgrade
Risk level: MEDIUM
Without PKCE (Proof Key for Code Exchange), an authorization code intercepted in transit (e.g., via a redirect URI mismatch or referrer leakage) can be exchanged for tokens by an attacker.
Mitigation:
Himayah enforces PKCE on all OAuth flows:
An intercepted authorization code is useless without the code_verifier — which never leaves the server.
8. XSS Session Token Theft
Risk level: HIGH
If session tokens are stored in localStorage or regular cookies, a single XSS vulnerability can exfiltrate all user sessions.
Mitigation:
Session cookies are set with:
HttpOnly— the cookie is completely inaccessible to JavaScript, even if an XSS payload runs on the pageSecure— the cookie is only sent over HTTPSSameSite=Lax— the cookie is not sent on cross-site POST requests, providing an additional CSRF layer
An XSS attack can call your own API endpoints (the cookie is attached automatically by the browser), but it cannot read or exfiltrate the session token value itself.
Reporting a Vulnerability
If you discover a security issue in Himayah, please disclose it responsibly by emailing the maintainers directly rather than opening a public GitHub issue. We aim to respond within 48 hours and publish a patch within 7 days.
