diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 14bd528..325d2ab 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -208,7 +208,7 @@ jobs: files: | docker-bake.hcl fpm/** - ${ matrix.webserver }/** + ${{ matrix.webserver }}/** dev/** - name: Build diff --git a/README.md b/README.md index 4d85b86..09ff9a7 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,5 @@ This repository contains a base image with Alpine + PHP + (Caddy or Nginx), which you can use to build your docker image with your code. [Documentation can be found here](https://developer.shopware.com/docs/guides/hosting/installation-updates/docker.html) + +The Nginx, Caddy and FrankenPHP configurations send `script-src 'none'; object-src 'none'; frame-src 'none'; base-uri 'none'; form-action 'none'` for static SVG files and existing HTML files under `public/media` and `public/thumbnail`. Application-rendered HTML and bundled HTML applications retain their own response policies. Custom static documents must work without scripts, embedded documents, base URL overrides or form submissions; images and styles remain permitted. Development images inherit the corresponding server configuration. diff --git a/caddy/rootfs/etc/caddy/Caddyfile b/caddy/rootfs/etc/caddy/Caddyfile index de3b052..bfa0953 100644 --- a/caddy/rootfs/etc/caddy/Caddyfile +++ b/caddy/rootfs/etc/caddy/Caddyfile @@ -6,6 +6,12 @@ log route { root * /var/www/html/public + @staticDocuments { + file + path_regexp staticDocuments (?i)([.]svg$|^/(media|thumbnail)/.*[.]html$) + } + header @staticDocuments Content-Security-Policy "script-src 'none'; object-src 'none'; frame-src 'none'; base-uri 'none'; form-action 'none'" + encode gzip zstd @theme path /theme/* diff --git a/frankenphp/rootfs/etc/caddy/Caddyfile b/frankenphp/rootfs/etc/caddy/Caddyfile index 2dd75ac..266cda4 100644 --- a/frankenphp/rootfs/etc/caddy/Caddyfile +++ b/frankenphp/rootfs/etc/caddy/Caddyfile @@ -12,6 +12,12 @@ :8000 { root * /var/www/html/public + @staticDocuments { + file + path_regexp staticDocuments (?i)([.]svg$|^/(media|thumbnail)/.*[.]html$) + } + header @staticDocuments Content-Security-Policy "script-src 'none'; object-src 'none'; frame-src 'none'; base-uri 'none'; form-action 'none'" + encode zstd gzip log diff --git a/nginx/rootfs/etc/nginx/nginx.conf b/nginx/rootfs/etc/nginx/nginx.conf index 9ae46d5..12325f6 100644 --- a/nginx/rootfs/etc/nginx/nginx.conf +++ b/nginx/rootfs/etc/nginx/nginx.conf @@ -48,6 +48,14 @@ http { deny all; } + # Stored HTML must not affect pages rendered by PHP. + location ~* ^/(media|thumbnail)/.*[.]html$ { + try_files $uri =404; + expires 1y; + add_header Cache-Control "public, must-revalidate, proxy-revalidate"; + add_header Content-Security-Policy "script-src 'none'; object-src 'none'; frame-src 'none'; base-uri 'none'; form-action 'none'"; + } + # Allow sitemap requests to hit the shopware application location ~ ^/sitemap/.*\.(xml|xml\.gz)$ { try_files $uri /index.php$is_args$args; @@ -64,7 +72,7 @@ http { open_file_cache_errors off; location ~* ^.+\.svg { - add_header Content-Security-Policy "script-src 'none'"; + add_header Content-Security-Policy "script-src 'none'; object-src 'none'; frame-src 'none'; base-uri 'none'; form-action 'none'"; add_header Cache-Control "public, must-revalidate, proxy-revalidate"; log_not_found off; } @@ -82,13 +90,13 @@ http { try_files $uri =410; location ~* ^.+\.svg { - add_header Content-Security-Policy "script-src 'none'"; + add_header Content-Security-Policy "script-src 'none'; object-src 'none'; frame-src 'none'; base-uri 'none'; form-action 'none'"; add_header Cache-Control "public, must-revalidate, proxy-revalidate"; log_not_found off; } } - location ~* ^.+\.(?:css|cur|js|jpe?g|gif|ico|png|svg|webp|html|woff|woff2|xml)$ { + location ~* ^.+\.(?:css|cur|js|jpe?g|gif|ico|png|webp|html|woff|woff2|xml)$ { expires 1y; add_header Cache-Control "public, must-revalidate, proxy-revalidate"; @@ -109,7 +117,10 @@ http { } location ~* ^.+\.svg$ { - add_header Content-Security-Policy "script-src 'none'"; + try_files $uri /index.php$is_args$args; + expires 1y; + add_header Cache-Control "public, must-revalidate, proxy-revalidate"; + add_header Content-Security-Policy "script-src 'none'; object-src 'none'; frame-src 'none'; base-uri 'none'; form-action 'none'"; } location ^~ /protected_files/ {