Set CSP policy for static assets for security hardeninng

This commit is contained in:
Jan Böhmer 2026-06-20 23:42:01 +02:00
parent 0cd83f0322
commit b62f47ba05
6 changed files with 29 additions and 9 deletions

View file

@ -51,6 +51,15 @@
# Disable Topics tracking if not enabled explicitly: https://github.com/jkarlin/topics
header ?Permissions-Policy "browsing-topics=()"
# Set a strict CSP and nosniff for all static assets not handled by PHP.
# ? means "set only if not already present", so PHP responses carrying a Nelmio CSP are left untouched.
header ?Content-Security-Policy "default-src 'self'; script-src 'none'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; sandbox;"
header ?X-Content-Type-Options "nosniff"
# SVG files get a slightly different CSP because they can embed resources and must not be framed.
@svg path *.svg *.svg.gz *.svg.br
header @svg Content-Security-Policy "default-src 'self'; script-src 'none'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; frame-ancestors 'none'; sandbox;"
# Prevent PHP execution in the media upload directory
@php_in_media path_regexp (?i)^/media/.*\.(php[3-8]?|phar|phtml|pht|phps)$
respond @php_in_media 403

View file

@ -193,7 +193,7 @@ RUN a2dissite 000-default.conf && \
a2enmod proxy_fcgi setenvif && \
a2enconf php${PHP_VERSION}-fpm && \
a2enconf docker-php && \
a2enmod rewrite
a2enmod rewrite headers
# Install composer and yarn dependencies for Part-DB
USER www-data

View file

@ -232,7 +232,7 @@ sudo ln -s /etc/apache2/sites-available/partdb.conf /etc/apache2/sites-enabled/p
Configure apache to show pretty URL paths for Part-DB (`/label/dialog` instead of `/index.php/label/dialog`):
```bash
sudo a2enmod rewrite
sudo a2enmod rewrite headers
```
If you want to access Part-DB via the IP-Address of the server, instead of the domain name, you have to remove the

View file

@ -36,6 +36,10 @@ server {
root /var/www/partdb/public;
location / {
# Headers are set here for static assets. PHP responses are served via the index.php location
# below and inherit neither of these headers, so Nelmio's PHP-side CSP is unaffected.
add_header Content-Security-Policy "default-src 'self'; script-src 'none'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; sandbox;" always;
add_header X-Content-Type-Options "nosniff" always;
try_files $uri /index.php$is_args$args;
}
@ -57,10 +61,12 @@ server {
location ~* ^/media/.*\.(php[3-8]?|phar|phtml|pht|phps)$ {
return 403;
}
# Set Content-Security-Policy for svg files, to block embedded javascript in there
# SVG files get a slightly different CSP because they can embed resources and must not be framed.
# This regex location takes precedence over location /, so headers must be repeated here.
location ~* \.svg$ {
add_header Content-Security-Policy "default-src 'self'; script-src 'none'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; frame-ancestors 'none';";
add_header Content-Security-Policy "default-src 'self'; script-src 'none'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; frame-ancestors 'none'; sandbox;" always;
add_header X-Content-Type-Options "nosniff" always;
}
error_log /var/log/nginx/parts.error.log;

View file

@ -119,9 +119,14 @@ DirectoryIndex index.php
</IfModule>
</IfModule>
# Set Content-Security-Policy for svg files (and compressed variants), to block embedded javascript in there
<IfModule mod_headers.c>
# Set a strict CSP for all static assets not handled by PHP.
# PHP responses already carry their own CSP via NelmioSecurityBundle, so setifempty leaves those untouched.
Header always setifempty Content-Security-Policy "default-src 'self'; script-src 'none'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; sandbox;"
Header always setifempty X-Content-Type-Options "nosniff"
# SVG files get a slightly different CSP because they can embed resources and must not be framed.
<FilesMatch "\.(svg|svg\.gz|svg\.br)$">
Header set Content-Security-Policy "default-src 'self'; script-src 'none'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; frame-ancestors 'none';"
Header always set Content-Security-Policy "default-src 'self'; script-src 'none'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; frame-ancestors 'none'; sandbox;"
</FilesMatch>
</IfModule>
</IfModule>

View file

@ -122,7 +122,7 @@ class AttachmentFileController extends AbstractController
private function setAttachmentCSPHeaders(Response $response): Response
{
//Set an CSP that disallow to run any scripts, styles or images from the attachment render page, as it is not used anywhere else for now and can be a security risk if used without proper precautions, so it should be opt-in
$response->headers->set('Content-Security-Policy', "default-src 'none'; script-src 'none'; style-src 'self' 'unsafe-inline'; img-src 'self'; sandbox;");
$response->headers->set('Content-Security-Policy', "default-src 'self'; script-src 'none'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; sandbox;");
return $response;
}