Files
pargar/docs/security.md
T
ahp 5b9b2a16e6 docs: add product overview and engineering documentation
Document architecture, security, deployment, and development for contributors.
2026-10-07 19:40:26 +03:30

57 lines
2.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Security
## Authentication and sessions
| Mechanism | Details |
|-----------|---------|
| Login | username/email + password + image CAPTCHA |
| Access JWT | Short-lived (~15 minutes) |
| Refresh | Hashed in DB; remember-me ≈ 30 days, short session ≈ 24 hours |
| Browser cookies | `pargar_access` / `pargar_refresh` — `HttpOnly`, `SameSite=Lax`, `Secure` when `PUBLIC_URL` is https |
| Frontend storage | Only `user` in `localStorage` (`pargar.auth`); tokens are not persisted |
| API | `credentials: "include"`; optional Bearer for tests/clients |
| Logout | Revoke refresh + clear cookies |
Public password recovery (`/api/auth/recovery/*` and `/recovery`) is disabled for students (404). Resets are admin-only and require the target account’s security answer.
## Secrets
- Outside `DEV_MODE`, `Validate()` rejects values like `change-me` / `local-dev-only` and JWTs shorter than 32 characters.
- Local Helm: generate-once; production: `existingSecret` required.
- `ADMIN_PASSWORD` only bootstraps when the admin user is missing; restarts do not overwrite the password.
## Proxy and CORS
- Only peers in `TRUSTED_PROXY_CIDRS` are trusted for `X-Forwarded-*` / `X-Real-IP`.
- CORS: `FRONTEND_ORIGINS` + `PUBLIC_URL` with `AllowCredentials: true`.
## Rate limiting
| Scope | Approximate behavior |
|-------|----------------------|
| Auth (login/register/captcha/refresh/recovery) | Redis per-IP budget; tighter after failures |
| Global `/api/*` | ~240 req/min/IP; 429 + user message + `Retry-After`; does not revoke tokens |
| External chat export | ~10/min/IP |
| Per-user uploads | Separately limited |
`/api/health` is excluded from the global ceiling.
## Uploads
| Type | Controls |
|------|----------|
| Admin video | Extension + MIME + magic (MP4/WebM) |
| Avatar | JPEG/PNG/WebP via magic only; client Content-Type is not trusted |
| Chat | Extension allow-list + sniff for image/video/audio/PDF/Office; raw public zip removed |
## Certificates and privacy
- Certificate URLs are unlisted; noindex via API, Traefik, Next, and robots.txt.
- Chat-export tokens are single-use, revocable, and redacted from logs/metric labels.
## Known trade-offs (current model)
- SameSite=Lax + same-origin instead of a separate CSRF token (adequate for this model; revisit if FE and API split domains).
- Donations and physical certificates have no online payment gateway — intentional.
- XSS remains dangerous; HttpOnly cookies reduce token theft from localStorage but do not eliminate XSS.