3

I have an nginx config that includes a CSP header that is served for all requests. Now I need to override it in one particular location (that also happens to be rewritten). I'm thinking something like this:

server {
  listen 80;
  listen [::]:80;

  server_name example.com;
  root /var/www;
  index index.php;

  try_files $uri @rewrites;

  add_header Content-Security-Policy "default-src 'self' ; script-src 'self' ; style-src 'self' 'unsafe-inline' ; img-src * 'self' data: ; font-src 'self' ; media-src * 'self' ; form-action 'self'";

  location @rewrites {
    rewrite ^/special/([0-9]*) /special.php?id=$1 last;
    rewrite ^/foo/([a-z]+) /foo.php?method=$1 last;
  }

  location /special {
    add_header Content-Security-Policy "default-src 'self' ; script-src 'self' 'unsafe-inline' ; style-src 'self' 'unsafe-inline' ; img-src * 'self' data: ; font-src 'self' ; media-src * 'self' ; form-action 'self'";
  }

  location ~ \.php$ {
    try_files $uri =404;
    fastcgi_split_path_info ^(.+?\.php)(/.*)$;
    include fastcgi_params;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_pass php;
  }
}

However, while that sets the header on any request starting with /special, it results in a 404 because it doesn't continue to the following location that maps PHP files. How should I do this?

3
  • Couldn't you merge @rewrites and /special?
    – gxx
    Aug 25, 2017 at 14:45
  • No - in reality @rewrites has many other entries that do not need the alternative header, but all it would mean is I have the same problem in a different place anyway. I've altered the Q to clarify.
    – Synchro
    Aug 25, 2017 at 14:49
  • I see, what about a map to assign the correct CSP header value depending on the request url?
    – gxx
    Aug 25, 2017 at 14:54

1 Answer 1

7

Try to the see if the following works for you:

http context:

map $request_uri $csp_header {
    default "default-src 'self' ; script-src 'self' ; style-src 'self' 'unsafe-inline' ; img-src * 'self' data: ; font-src 'self' ; media-src * 'self' ; form-action 'self'";
    "~^/special" "default-src 'self' ; script-src 'self' 'unsafe-inline' ; style-src 'self' 'unsafe-inline' ; img-src * 'self' data: ; font-src 'self' ; media-src * 'self' ; form-action 'self'";
}

server context:

add_header Content-Security-Policy $csp_header;
5
  • 1
    Thanks, that works - I needed to change the match string to "~^/special" to make it work as a prefix – the matching mechanism is annoyingly different to that used in location. It's a shame that it has to be defined outside the server context too.
    – Synchro
    Aug 25, 2017 at 15:19
  • 1
    @Synchro Great, I'll incorporate your fix, thanks! Did you use "~^/special", with ".."?
    – gxx
    Aug 25, 2017 at 15:24
  • 2
    @Synchro Also, as it seems the values are nearly identical, and to reduce code duplication: You could try to only differentiate script-src and to keep the rest the same, but I'm unsure if that works later on while adding the header (using a var in a quoted directive). I fear it's not possible, but in case you try it out, I would be interested in feedback.
    – gxx
    Aug 25, 2017 at 15:31
  • This is a really great help! Do you have any idea about de-duplicating the CSP string itself? Either way, thank you!
    – Slbox
    Feb 24, 2020 at 23:20
  • @Sibox Not sure if I get you right, but maybe the above comment helpful. I'm not completely sure if that's possible, but in case you try it out, I'm interested in how it goes.
    – gxx
    Feb 25, 2020 at 0:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .