Built by a security professional
Security by design
Every layer of this platform was built with security in mind — from how passwords are stored to how HTTP headers are sent. Here's exactly what's in place and why.
← Back to homeAuthentication & Sessions
Cost factor 12 — calibrated to be slow enough to resist offline brute-force attacks while staying fast enough for legitimate logins.
Sessions are signed JWTs — no server-side session table, no shared session store. Tokens are invalidated at sign-out.
Passwords must be 8–128 characters. The upper bound prevents bcrypt DoS attacks that exploit bcrypt's CPU cost on very long inputs.
An email address can only be tied to one account regardless of provider (credentials, GitHub, or Google). Cross-provider hijacking is blocked at the auth callback before any upsert.
Rate Limiting & Abuse Prevention
10 attempts per IP per 15 minutes. Sliding-window counter, resets cleanly. Failed attempts beyond the limit return 429 with no further DB queries.
5 registrations per IP per 15 minutes — makes scripted account creation costly without impacting legitimate users.
20 onboarding requests per IP per hour — limits username enumeration via repeated attempts.
Reads X-Forwarded-For (Railway's edge) then X-Real-IP as fallback; the leftmost address is taken to prevent header spoofing.
Transport & HTTP Headers
All traffic is HTTPS. HSTS (max-age=31536000; includeSubDomains) is set so browsers refuse plain HTTP connections for one year after the first visit.
CSP restricts script, style, image, font, and frame sources. Scripts are limited to 'self'; object-src and base-uri are locked to 'none' and 'self' respectively to block injection and redirect attacks.
Prevents the site from being embedded in a third-party iframe, blocking clickjacking attacks.
Prevents browsers from MIME-sniffing a response away from the declared content type.
Explicitly disables camera, microphone, and geolocation access — no accidental capability grants.
Sends the full referrer on same-origin requests but only the origin on cross-origin ones, preventing URL leakage.
File Upload Protection
The first 12 bytes of every uploaded file are read and checked against known file signatures (JPEG: FF D8 FF, PNG: 89 50 4E 47 0D 0A 1A 0A, WebP: RIFF…WEBP, GIF: GIF8). Declared MIME type alone is not trusted.
Only JPEG, PNG, WebP, and GIF pass validation. All other types are rejected with 415 Unsupported Media Type before the file is written.
Uploads exceeding 5 MB are rejected at the API boundary.
Files are written as headshot-{userId}.{ext} — predictable per user, collision-safe across users, and no path traversal possible.
When a new headshot is uploaded, the previous file under /uploads/ is deleted server-side, preventing unbounded storage accumulation.
Data Integrity & Input Validation
All database access goes through Prisma, which uses parameterized queries exclusively. Raw SQL injection is structurally impossible.
Every API route validates shape, type, and length before touching the database. Invalid payloads return 422 Unprocessable Entity — never a 500 that might leak stack traces.
Foreign-key relationships use onDelete: Cascade so removing a user atomically removes all their content — no orphaned rows, no data leakage to future users who might reuse an ID.
OAuth upserts never overwrite the stored email field after account creation, preventing a provider-side email change from silently retaking an account.
Access Control
requireAuth() is called at the top of every admin API handler. Unauthenticated requests receive 401 before any query runs.
Every write operation binds to the authenticated userId from the JWT — not from the request body. A user cannot modify another user's content even with a crafted payload.
The admin layout verifies the URL username matches the session username. Visiting /{someone-else}/admin redirects to your own admin panel.
A GitHub or Google sign-in can only access the account that was originally created with that provider identity. Email conflicts across providers are blocked at the signIn callback, not post-creation.
This platform is maintained by a professional cybersecurity administrator. Security controls are not an afterthought — they are part of the architecture. Practices are reviewed and updated as the threat landscape evolves.