This document summarizes the security posture of Rondivu and provides guidance for safe deployment.
- bcrypt (cost 12) for password hashing
- JWT sessions (24h, HttpOnly, SameSite=Lax, Secure in production)
- Permission-based access: Create Event, Modify Settings gated by user roles
- Admin key for event management: treat as a shared secret; anyone with it can manage the event
- Open redirect prevention:
returnToin login/setup/migrate is validated server-side; only relative paths (/...) are accepted - Email provider whitelist:
providermust benone,smtp, orresend;smtpSecuremust betrue/false/1/0 - Event creation: Zod schema validates title (max 140), description (2000), guests, etc.
- Guest message: Truncated to 2000 characters server-side; client enforces
maxLength
- React escapes all user content by default (no
dangerouslySetInnerHTML) - Guest names, messages, notes, event titles rendered as text
X-Frame-Options: SAMEORIGINX-Content-Type-Options: nosniffReferrer-Policy: strict-origin-when-cross-originPermissions-Policy: camera, microphone, geolocation disabled
- Session secret stored in DB, generated on first setup
- SMTP/Resend credentials stored in DB (Settings); env vars override when set
- Admin and guest tokens are high-entropy (base64url, 18–24 bytes)
- HTTPS only: Ensure
NODE_ENV=productionand your reverse proxy (Nginx, Caddy, etc.) terminates TLS - Database: Prefer PostgreSQL for production; SQLite is fine for single-user/low-traffic
- Email: Configure SMTP or Resend and set
APP_URLto your public base URL - Backups: Regularly backup the database and
prisma/migrations
- In production, cookies use
Secureonly whenNODE_ENV === "production" - If running behind HTTPS with a different NODE_ENV, consider setting
secure: trueinauth.tsexplicitly
| Topic | Notes |
|---|---|
| Admin key in URL | Event admin links include ?key=.... These URLs appear in logs, browser history, and referrer headers. Treat them as secrets; don't share publicly. |
| User enumeration | Login returns the same "Incorrect email or password" for invalid email vs wrong password to avoid leaking account existence. |
| Guest token auth | RSVP is authorized by guest token only. Tokens are unguessable; possession = authorization. |
- Rate limiting: Add rate limits for login, invite, and RSVP actions (e.g. 5 attempts per IP per 15 min)
- Account lockout: After N failed logins, temporary lock or captcha
- CSP: Add Content-Security-Policy header (may require tuning for inline scripts if any)
- Audit logging: Log sensitive actions (login, invite sent, user created) for forensics
If you discover a security issue, please report it responsibly. See the project’s GitHub security policy or contact the maintainers directly.