mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 19:19:19 +02:00
Items resolved: - #3 (HIGH): Move file uploads outside webroot to STORAGE_ROOT (/var/www/posterg/storage). Uploads were previously stored in public/admin/actions/data/ which is web-accessible. - #4 (HIGH): Align file paths and add media.php controller. DB paths are now storage-relative (theses/YEAR/ID/file, covers/file). New public/media.php serves files with path-traversal jail, MIME allow-list, and proper caching headers. memoire.php and search.php updated to use /media.php?path=. Also fixed: cover images were never recorded in thesis_files (broken INSERT). - #5 (HIGH): RateLimit::getClientIdentifier() now uses REMOTE_ADDR only. HTTP_X_FORWARDED_FOR and HTTP_CLIENT_IP are attacker-controlled headers that allowed unlimited rate-limit bypass by rotating spoofed IPs. - #6 (HIGH): Port public/admin/.htaccess security rules to nginx/posterg.conf. Apache .htaccess directives are silently ignored by nginx; none were active. CSP added to /admin/ location block, .log file denial added globally, autoindex off made explicit. Documented in nginx/HTACCESS_TO_NGINX.md. Supporting changes: - config/bootstrap.php: add STORAGE_ROOT constant - nginx/SECURITY_HEADERS.md: updated to reflect admin CSP and pending public CSP - docs/TODO.SECURITY.md: items #3-6 moved to resolved; priority order updated
2.2 KiB
2.2 KiB
.htaccess → nginx migration (item #6)
Problem:
public/admin/.htaccesscontained Apache-specific security directives that nginx silently ignores. None of the rules were active in production.
Rules migrated into nginx/posterg.conf
Apache .htaccess rule |
nginx equivalent | Location |
|---|---|---|
Header always set X-Frame-Options "SAMEORIGIN" |
add_header X-Frame-Options "SAMEORIGIN" always; |
main server block (already present) |
Header always set X-Content-Type-Options "nosniff" |
add_header X-Content-Type-Options "nosniff" always; |
main server block (already present) |
Header always set X-XSS-Protection "1; mode=block" |
Intentionally omitted — deprecated & counterproductive; see SECURITY_HEADERS.md |
— |
Header always set Referrer-Policy "strict-origin-when-cross-origin" |
add_header Referrer-Policy "strict-origin-when-cross-origin" always; |
main server block (already present) |
Header always set Content-Security-Policy "..." |
add_header Content-Security-Policy "..." always; |
/admin/ location block (added) |
Options -Indexes |
autoindex off; |
/admin/ location block (added; nginx default is off, explicit for clarity) |
<FilesMatch "^\."> Require all denied |
location ~ /\.(?!well-known).* deny |
main server block (already present) |
<FilesMatch "(composer\.(json|lock)|error\.log)$"> Require all denied |
location ~* \.(md|txt|sql|sh|json|gitignore)$ deny + location ~* \.log$ deny |
main server block (log rule added) |
php_flag display_errors Off |
Handled by config/bootstrap.php (ini_set('display_errors', '0')) |
PHP |
php_flag log_errors On |
Handled by config/bootstrap.php (ini_set('log_errors', '1')) |
PHP |
php_value error_log error.log |
Handled by config/bootstrap.php; should use absolute path (item #9) |
PHP |
Status of public/admin/.htaccess
The file is now dead code on this nginx server. It has been left in place
(harmless) so it would still work if the project were ever tested behind Apache
(e.g., php -S built-in server doesn't read it either). All security rules it
previously attempted to set are now enforced by nginx directly.
Added: 2026-02-08 — security item #6