mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 11:09:18 +02:00
- Moved /lib → /src (PHP source code)
- Moved /includes → /public/includes (main site templates)
- Admin section remains self-contained in /public/admin with its own /inc
- Updated all require/include paths across codebase
- Updated config/bootstrap.php, justfile, tests, docs
- All tests passing ✅
Structure now follows PHP best practices:
/config - Configuration files
/database - SQLite database + schema
/docs - Documentation (intact)
/nginx - Server config (intact)
/public - Web-accessible files (entry point)
/admin - Self-contained admin interface
/assets - CSS, fonts, icons
/includes - Main site templates (header/footer)
/scripts - Deployment scripts (intact)
/src - PHP source classes (Database, AdminAuth, RateLimit)
/tests - Test suites
4.9 KiB
4.9 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. |
| 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 | src/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 | src/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
- 🔴 CRITICAL — ✅ All done (items 1–2)
- 🟡 MEDIUM — Items 7, 9, 11, 12 (sanitisation standardisation, error log, CSP, CSV MIME) — item 8 resolved with item 2
- 🔵 LOW — ✅ All done (items 13–16)
Last updated: 2026-02-08