Files
xamxam/docs/security.md
T
Pontoporeia 55c714a35d Reorganise docs: move historical files to archive/, merge overlapping docs
- Move 12 historical/superseded docs + 1 session log + 1 PDF + 1 HTML plan to archive/
- Merge 4 VM-crash docs into archive/vm-crash-incident.md
- Merge LDAP plan + spec into ldap.md
- Merge FilePond race investigation into filepond-crash-analysis.md
- Merge SPECS.md client notes into spec-sheet.md appendix
- Update README index and security.md cross-reference
2026-08-24 11:36:02 +02:00

3.8 KiB

Security

Current security posture for XAMXAM.

This supersedes the earlier security.md (2026-02-08 audit). The original 16-item audit is closed; the items below reflect the current state.


Authentication — admin

  • PHP session auth: app/src/AdminAuth.php. Password-only (no username). Credentials previously in a gitignored PHP file; the current build stores the bcrypt hash in site_settings.admin_password_hash (manageable from /admin/account).
  • AdminAuth::requireLogin() guards every admin action/route.
  • Session cookies hardened: HttpOnly, SameSite=Strict, Secure, Path=/admin; regenerated on login.
  • nginx auth_basic layer has been removed; the PHP session layer is the only gate. (LDAP-based login is a proposed future enhancement — see ldap.md. It is not implemented.)

Transport & headers

Enforced in nginx/xamxam.conf (see nginx/docs/SECURITY_HEADERS.md):

  • HSTS (Strict-Transport-Security, 730 days, preload)
  • CSP — default-src 'self'; … frame-ancestors 'none' on public pages; frame-ancestors 'self' where the app embeds allowed content; admin CSP includes script-src 'unsafe-inline' for the OverType editor. object-src 'none'.
  • X-Frame-Options: DENY (clickjacking)
  • X-Content-Type-Options: nosniff
  • Referrer-Policy: strict-origin-when-cross-origin
  • Permissions-Policy (geo/mic/camera disabled)
  • Cross-Origin-Opener-Policy / Cross-Origin-Resource-Policy: same-origin
  • X-Robots-Tag: noindex, nofollow on /admin/

X-XSS-Protection is intentionally omitted (deprecated; see nginx/docs/SECURITY_HEADERS.md for rationale).

Rate limiting

Defined in the nginx config limit_req_zone and enforced by app/src/RateLimit.php:

  • General requests: 30 r/m
  • Search endpoint: 30 r/m
  • Admin panel: 300 r/m (burst 30)

The PHP limiter uses REMOTE_ADDR only (not X-Forwarded-For) to avoid IP spoofing.

Files & storage

  • Uploads live outside the webroot under app/storage/ (tfe/, theses/), served on demand via MediaController/FileAccessController through controlled endpoints (/media), not direct static access.
  • nginx blocks /storage, /src, /templates, DB/sql/env/md files, and hidden files. The DocumentRoot is app/public/ only.
  • Restricted-file downloads are gated by a request/approval/token flow (file_access_* tables).
  • Logs write to /var/log/xamxam/ in production (and app/storage/logs/ only in dev/cli-server) — outside the webroot, not publicly served.

Injection & output

  • SQL: all queries use PDO prepared statements.
  • LIKE wildcards: Database::escapeLikeString() escapes % and _ (public search and related queries).
  • XSS: htmlspecialchars() on all user-controlled output; integer/ID inputs cast.
  • CSRF: per-session tokens (bin2hex(random_bytes(32))), compared with hash_equals().
  • File uploads: MIME validated (finfo); FilePond prevalidation + server-side checks in FilepondHandler.
  • Markdown/HTML: user content (pages, help blocks) rendered via league/commonmark; HTML in admin-editable content is expected.

Defence in depth / misc

  • External links use rel="noopener noreferrer".
  • Decryption/Crypto failures are logged without leaking secrets; SMTP password is stored encrypted in smtp_settings and rotated via just reencrypt-password.
  • Admin operations are recorded in admin_audit_log (resource, action, status, IP, User-Agent).

Areas to keep monitored

  • Tightening the public CSP (frame-ancestors 'none' vs 'self' on embed routes) is an active topic — see TODO.md.
  • Sensitive file downloads and their expiry/token handling are worth periodic review as usage grows.

See also: nginx/docs/SECURITY_HEADERS.md, nginx/docs/PHP_AUTH_LAYER.md, nginx/docs/PRODUCTION_DEPLOYMENT.md.