Files
xamxam/docs/TODO.SECURITY.md
Théophile Gervreau-Mercier 8613f71112 security: add PHP session auth guard for admin panel (item #2, CRITICAL)
- lib/AdminAuth.php: new class with requireLogin(), login(), logout(),
  isAuthenticated(); starts session with hardened cookie params
  (HttpOnly, SameSite=Strict, Secure, Path=/admin) — also resolves
  item #8 (session cookie hardening)
- requireLogin() auto-authenticates from nginx Basic Auth credentials
  ($_SERVER['PHP_AUTH_PW']) so the user only sees one browser prompt;
  falls back to /admin/login.php if the proxy is absent/misconfigured
- config/admin_credentials.php: gitignored credential store; define
  ADMIN_PASSWORD_HASH with a bcrypt hash to enable PHP auth
- config/admin_credentials.example.php: template for the above
- config/bootstrap.php: auto-loads admin_credentials.php if present
- .gitignore: exclude config/admin_credentials.php
- public/admin/login.php: fallback login form (shown only when nginx
  Basic Auth is bypassed / proxy absent)
- public/admin/logout.php: session destruction + redirect to login
- All 7 admin PHP files: replace session_start() with
  AdminAuth::requireLogin() (defence-in-depth behind nginx Basic Auth)
- public/admin/inc/head.php: Déconnexion button when ADMIN_PASSWORD_HASH
  is defined
- nginx/PHP_AUTH_LAYER.md: documents dual-auth architecture, UX flow,
  and setup instructions
- docs/TODO.SECURITY.md: items #2 and #8 moved to Resolved; priority
  order updated (all CRITICAL done)
2026-02-08 14:22:45 +01:00

4.9 KiB
Raw Blame History

🔒 Security TODO — posterg-website

Based on docs/SECURITY_ANALYSIS.md (2026-02-08).
Tracks resolution status for all identified vulnerabilities.


Resolved

Infrastructure / Deployment

# Issue Severity Resolution
1 No HTTPS — admin credentials exposed in transit 🔴 CRITICAL TLS is terminated upstream by the reverse proxy (outside nginx). nginx.conf does not need to handle TLS directly.
3 Uploaded files stored inside the webroot 🟠 HIGH Storage moved to STORAGE_ROOT (/var/www/posterg/storage/), defined in config/bootstrap.php. formulaire.php updated.
4 File path mismatch — media files broken and insecure 🟠 HIGH DB paths are now storage-relative (theses/YEAR/ID/file, covers/file). New controller public/media.php serves files safely. memoire.php and search.php updated to use /media.php?path=…. Cover recording in formulaire.php fixed (was never inserted into DB).
5 Rate limiter bypassed by IP spoofing (X-Forwarded-For) 🟠 HIGH lib/RateLimit.php getClientIdentifier() now uses REMOTE_ADDR only.
6 .htaccess security rules silently ignored by nginx 🟠 HIGH All rules ported to nginx/posterg.conf (CSP to /admin/ block, .log denial, autoindex off). See nginx/HTACCESS_TO_NGINX.md.
13 Deprecated X-XSS-Protection header 🔵 LOW Removed from nginx/posterg.conf; see nginx/SECURITY_HEADERS.md for rationale.

Frontend / Assets

# Issue Severity Resolution
10 CDN stylesheet (water.css) without Subresource Integrity 🟡 MEDIUM CDN will not be used in production. The stylesheet will be self-hosted, eliminating the supply-chain risk entirely.

Frontend

# Issue Severity Resolution
14 Missing rel="noreferrer" on external target="_blank" links 🔵 LOW rel="noopener noreferrer" applied in public/admin/thanks.php.

Code Quality / Defence in Depth

# Issue Severity Resolution
15 Unescaped integer outputs (inconsistency) 🔵 LOW Explicit (int) casts added in public/index.php and public/search.php.
16 Redundant DATABASE_PATH constant never used 🔵 LOW define('DATABASE_PATH', …) removed from config/bootstrap.php.

Admin Panel — Authentication & Sessions

# Issue Severity Resolution
2 No PHP-level authentication in admin panel 🔴 CRITICAL lib/AdminAuth.php implements a session guard with password_verify + session_regenerate_id. All admin PHP files now call AdminAuth::requireLogin() instead of bare session_start(). Credentials stored in gitignored config/admin_credentials.php (define ADMIN_PASSWORD_HASH). No-op when constant is absent (dev / cli-server). Also resolves item #8 (session cookie hardening via session_set_cookie_params before session_start). See nginx/PHP_AUTH_LAYER.md.
8 Session cookies not hardened (Secure, HttpOnly, SameSite missing) 🟡 MEDIUM Resolved as part of item #2. AdminAuth::startSession() sets HttpOnly=true, SameSite=Strict, Secure=true (off on cli-server), Path=/admin, Lifetime=0 before every session_start().

🔧 In Progress

Database / Input Handling

# Issue Severity Status
7 LIKE wildcard injection in admin search (public/admin/index.php) 🟡 MEDIUM Needs standardisation of DB input sanitisation across the whole codebase. The public Database::searchTheses() already escapes % and _ correctly; the same pattern must be applied to admin search and any other raw LIKE queries.

Not Yet Implemented

Infrastructure / Deployment

# Issue Severity Files
11 Missing Content-Security-Policy on public pages 🟡 MEDIUM nginx/posterg.conf → add Content-Security-Policy header to main server block (admin already has CSP via item #6)

Admin Panel — Error Logging

# Issue Severity Files
9 error.log written to a web-accessible path 🟡 MEDIUM public/admin/actions/formulaire.php → use absolute path outside webroot

File Import

# Issue Severity Files
12 CSV import missing server-side MIME validation 🟡 MEDIUM public/admin/import.php → add finfo MIME check

Priority Order for Remaining Work

  1. 🔴 CRITICAL All done (items 12)
  2. 🟡 MEDIUM — Items 7, 9, 11, 12 (sanitisation standardisation, error log, CSP, CSV MIME) — item 8 resolved with item 2
  3. 🔵 LOW All done (items 1316)

Last updated: 2026-02-08