Security
Controls for secrets, token rotation, email verification, and trusted proxy boundaries.
Use this page to keep production deployments from exposing test surfaces, stale auth reads, leaked secrets, or untrusted client IP headers.
Production Exposure
- Production must use
configs/static_config.prod.yaml. - Testsuite and tests-control handlers must not be mounted in internet-facing environments.
- Serve only behind TLS and a controlled reverse proxy.
- Set request size limits and edge rate limits before traffic reaches the service.
Secrets
| Secret | Storage | Rotation trigger |
|---|---|---|
| JWT private key | Secret store mounted as a file with restricted permissions. | Scheduled rotation, suspected exposure, or signing key compromise. |
| SMTP password | Secret store or deployment-time generated config. | Any exposure in chat, logs, screenshots, local files, or git history. |
| Database password | Secret store and database role manager. | Staff offboarding, exposure, or periodic credential rotation. |
Authentication Consistency
Credential checks, session lookup, revocation checks, password changes, refresh-token reuse detection, and token-family revocation are auth-critical paths. They must read from strongly consistent storage, not from a lagging replica. Replica lag can temporarily allow old passwords, revoked sessions, or missed reuse detection.
Session and Token Controls
- Access tokens are short-lived RS256 JWTs.
- Refresh tokens are delivered only through the
refresh_tokenHttpOnly Secure cookie. - Refresh tokens are stored as hashes and rotated on each refresh.
- Detected refresh-token reuse revokes the whole token family.
- Password change revokes active sessions so clients must sign in again.
Email Verification Controls
- Verification uses POST JSON bodies, not query-string secrets.
- Verification codes are generated with a cryptographically secure generator and stored as hashes.
- Attempts and resend requests are rate-limited by email, user, and client IP signals.
- Outbox payloads containing sensitive code material are cleared after successful delivery or terminal failure.
- Resend invalidates the previous active code before creating a fresh one.
Client IP Trust
X-Forwarded-For and X-Real-IP are untrusted user input unless the request came from a
configured trusted proxy CIDR. Store normalized IP values only after parsing and validation. This affects
session metadata, sign-up/sign-in rate limits, and verification rate limits.
IPv4-mapped IPv6 peers such as ::ffff:127.0.0.1 are canonicalized to IPv4 before trusted-proxy
matching and rate-limit key selection.
Logging Rules
- Do not log passwords, refresh tokens, raw cookies, refresh token pepper, JWT private keys, SMTP credentials, or verification codes.
- Use correlation ids for SMTP outbox jobs and auth errors.
- Keep production log level at
infounless debugging an active incident in a controlled window.
Registration Controls
Sign-up, sign-in, email verification, and password reset have shared PostgreSQL-backed application limits. Registration consumes an atomic per-IP slot after validation and before uniqueness checks or password hashing. Edge request-size, burst, and path limits remain required as defense in depth.