mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 11:09:18 +02:00
Deduplicate and standardise documentation
- Consolidate 36 markdown files → 14 (plus TODO.md) - Merge overlapping docs into authoritative files: - database.md (from DATABASE_SPECIFICATION + QUICK_SCHEMA_REFERENCE + DATABASE_CONFIG + SETUP) - deployment.md (from SERVER_SETUP + COMPLETE_DEPLOYMENT_GUIDE + DEPLOYMENT_STEPS) - security.md (from SECURITY_ANALYSIS + TODO.SECURITY) - development.md (from DEVELOPMENT_GUIDE + LIVE_RELOAD_SETUP + TEST_CENTRALIZATION) - migration-history.md (from 11 past migration docs) - Standardise all filenames to lowercase - Remove non-doc files (Context.md research notes, chat export) - Remove superseded docs (SECURITY.md pre-SQLite, SECURITY_IMPLEMENTATION, README_SECURE_SEARCH) - Fix stale cross-references
This commit is contained in:
82
docs/security.md
Normal file
82
docs/security.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# Security
|
||||
|
||||
Vulnerability analysis and resolution status for posterg-website.
|
||||
|
||||
> Based on security audit (2026-02-08). All items tracked below.
|
||||
|
||||
---
|
||||
|
||||
## Resolved
|
||||
|
||||
### Infrastructure / Deployment
|
||||
|
||||
| # | Issue | Severity | Resolution |
|
||||
|---|-------|----------|------------|
|
||||
| 1 | No HTTPS — admin credentials exposed in transit | 🔴 CRITICAL | TLS terminated upstream by reverse proxy. nginx.conf doesn't need to handle TLS directly. |
|
||||
| 3 | Uploaded files stored inside webroot | 🟠 HIGH | Storage moved to `STORAGE_ROOT` (`/var/www/posterg/storage/`), defined in `config/bootstrap.php`. |
|
||||
| 4 | File path mismatch — media broken & insecure | 🟠 HIGH | DB paths now storage-relative. New `public/media.php` serves files safely. `memoire.php` and `search.php` use `/media.php?path=…`. Cover recording fixed. |
|
||||
| 5 | Rate limiter bypassed by IP spoofing (`X-Forwarded-For`) | 🟠 HIGH | `src/RateLimit.php` `getClientIdentifier()` uses `REMOTE_ADDR` only. |
|
||||
| 6 | `.htaccess` rules silently ignored by nginx | 🟠 HIGH | All rules ported to `nginx/posterg.conf`. See `nginx/HTACCESS_TO_NGINX.md`. |
|
||||
| 13 | Deprecated `X-XSS-Protection` header | 🔵 LOW | Removed from `nginx/posterg.conf`. |
|
||||
|
||||
### Frontend / Assets
|
||||
|
||||
| # | Issue | Severity | Resolution |
|
||||
|---|-------|----------|------------|
|
||||
| 10 | CDN stylesheet without SRI | 🟡 MEDIUM | CDN will not be used in production. Self-hosted, eliminating supply-chain risk. |
|
||||
|
||||
### Code Quality / Defence in Depth
|
||||
|
||||
| # | Issue | Severity | Resolution |
|
||||
|---|-------|----------|------------|
|
||||
| 14 | Missing `rel="noreferrer"` on external links | 🔵 LOW | `rel="noopener noreferrer"` applied in `public/admin/thanks.php`. |
|
||||
| 15 | Unescaped integer outputs | 🔵 LOW | Explicit `(int)` casts added in `public/index.php` and `public/search.php`. |
|
||||
| 16 | Redundant `DATABASE_PATH` constant | 🔵 LOW | Removed from `config/bootstrap.php`. |
|
||||
|
||||
### Admin Panel — Authentication & Sessions
|
||||
|
||||
| # | Issue | Severity | Resolution |
|
||||
|---|-------|----------|------------|
|
||||
| 2 | No PHP-level authentication in admin | 🔴 CRITICAL | `src/AdminAuth.php` implements session guard with `password_verify` + `session_regenerate_id`. All admin files call `AdminAuth::requireLogin()`. Credentials in gitignored `config/admin_credentials.php`. No-op when constant absent (dev/cli-server). |
|
||||
| 8 | Session cookies not hardened | 🟡 MEDIUM | Resolved with #2. `AdminAuth::startSession()` sets `HttpOnly=true`, `SameSite=Strict`, `Secure=true` (off on cli-server), `Path=/admin`, `Lifetime=0`. |
|
||||
|
||||
---
|
||||
|
||||
## In Progress
|
||||
|
||||
| # | Issue | Severity | Status |
|
||||
|---|-------|----------|--------|
|
||||
| 7 | LIKE wildcard injection in admin search | 🟡 MEDIUM | Public `Database::searchTheses()` escapes `%` and `_` correctly. Same pattern must be applied to admin search and any other raw LIKE queries. |
|
||||
|
||||
---
|
||||
|
||||
## Not Yet Implemented
|
||||
|
||||
| # | Issue | Severity | Files |
|
||||
|---|-------|----------|-------|
|
||||
| 11 | Missing Content-Security-Policy on public pages | 🟡 MEDIUM | `nginx/posterg.conf` → add CSP header to main server block |
|
||||
| 9 | `error.log` in web-accessible path | 🟡 MEDIUM | `public/admin/actions/formulaire.php` → use absolute path outside webroot |
|
||||
| 12 | CSV import missing server-side MIME validation | 🟡 MEDIUM | `public/admin/import.php` → add `finfo` MIME check |
|
||||
|
||||
---
|
||||
|
||||
## Priority Order
|
||||
|
||||
1. ~~🔴 CRITICAL~~ — All done (items 1–2)
|
||||
2. 🟡 **MEDIUM** — Items 7, 9, 11, 12 remaining
|
||||
3. ~~🔵 LOW~~ — All done (items 13–16)
|
||||
|
||||
---
|
||||
|
||||
## Good Practices Already in Place
|
||||
|
||||
- ✅ SQL injection: all queries use PDO prepared statements
|
||||
- ✅ XSS output: `htmlspecialchars()` on all user-controlled output
|
||||
- ✅ CSRF: tokens with `bin2hex(random_bytes(32))`, validated with `hash_equals()`
|
||||
- ✅ File upload: MIME type validated with `finfo`
|
||||
- ✅ Input validation: year, IDs, pagination cast to integers
|
||||
- ✅ LIKE wildcard escaping in public search (`Database::escapeLikeString`)
|
||||
|
||||
---
|
||||
|
||||
*Last updated: 2026-02-08*
|
||||
Reference in New Issue
Block a user