1

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?

  • Couldn't you merge @rewrites and /special? – gf_ Aug 25 '17 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 '17 at 14:49
  • I see, what about a map to assign the correct CSP header value depending on the request url? – gf_ Aug 25 '17 at 14:54
1

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;
  • 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 '17 at 15:19
  • @Synchro Great, I'll incorporate your fix, thanks! Did you use "~^/special", with ".."? – gf_ Aug 25 '17 at 15:24
  • 1
    @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. – gf_ Aug 25 '17 at 15:31

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.