mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 11:09:18 +02:00
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.
4.8 KiB
4.8 KiB
🔒 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
- 🔴 CRITICAL — Item 2 (add simple PHP session auth guard)
- 🟠 HIGH — Items 3, 4, 5, 6 (file storage overhaul + nginx hardening + rate-limiter fix)
- 🟡 MEDIUM — Items 7, 8, 9, 11, 12 (sanitisation standardisation, session hardening, CSP, error log, CSV MIME)
- 🔵 LOW — ✅ All done (items 13–16)
Last updated: 2026-02-08