Files
xamxam/docs/TODO.SECURITY.md
Théophile Gervreau-Mercier f5d3281c43 security: fix all LOW priority items from TODO.SECURITY.md
Item 13 — Remove deprecated X-XSS-Protection header
- nginx/posterg.conf: header removed (was '1; mode=block')
- nginx/SECURITY_HEADERS.md: new file documenting header decisions
  and explaining why X-XSS-Protection is counterproductive

Item 14 — Add rel="noreferrer" to external target="_blank" link
- public/admin/thanks.php: rel="noopener" → rel="noopener noreferrer"

Item 15 — Explicit (int) casts on all integer HTML outputs
- public/index.php: (int) on item id, page numbers
- public/search.php: (int) on totalItems, year options, item id, pagination

Item 16 — Remove unused DATABASE_PATH constant
- config/bootstrap.php: define('DATABASE_PATH', ...) removed

docs/TODO.SECURITY.md updated: items 13-16 marked resolved and
moved to the  Resolved section.
2026-02-08 13:54:02 +01:00

4.8 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.
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.

🔧 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
6 .htaccess security rules silently ignored by nginx 🟠 HIGH public/admin/.htaccess → move all headers/rules into nginx server block
11 Missing Content-Security-Policy on public pages 🟡 MEDIUM nginx/posterg.conf → add Content-Security-Policy header
13 Deprecated X-XSS-Protection header 🔵 LOW nginx/posterg.conf — header removed; documented in nginx/SECURITY_HEADERS.md

Admin Panel — Authentication & Sessions

# Issue Severity Files / Notes
2 No PHP-level authentication in admin panel 🔴 CRITICAL All public/admin/*.php files. The reverse proxy + nginx Basic Auth is the only auth layer — a single point of failure. CSRF ≠ authentication (CSRF only prevents cross-site forgery on already-open sessions; it does nothing against a direct unauthenticated request). A simple PHP session guard adds real defence-in-depth for ~20 lines using stdlib (password_verify, session_regenerate_id) with negligible added attack surface — the risk of not having it (proxy misconfiguration, bypass, local dev without proxy) outweighs the risk of adding it.
8 Session cookies not hardened (Secure, HttpOnly, SameSite missing) 🟡 MEDIUM All admin PHP files using session_start()

File Upload / Storage

# Issue Severity Files
3 Uploaded files stored inside the webroot 🟠 HIGH public/admin/actions/formulaire.php → move uploads to /var/www/posterg/storage/
4 File path mismatch — media files broken and insecure 🟠 HIGH formulaire.php, memoire.php, search.php → align stored paths with a controller-served endpoint
9 error.log written to a web-accessible path 🟡 MEDIUM public/admin/actions/formulaire.php → use absolute path outside webroot

Rate Limiting

# Issue Severity Files
5 Rate limiter bypassed by IP spoofing (X-Forwarded-For) 🟠 HIGH lib/RateLimit.php → use REMOTE_ADDR only

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 — Item 2 (add simple PHP session auth guard)
  2. 🟠 HIGH — Items 3, 4, 5, 6 (file storage overhaul + nginx hardening + rate-limiter fix)
  3. 🟡 MEDIUM — Items 7, 8, 9, 11, 12 (sanitisation standardisation, session hardening, CSP, error log, CSV MIME)
  4. 🔵 LOW All done (items 1316)

Last updated: 2026-02-08