'add_header' no longer allowed inside 'if', even though document says it is?

Hi!

I’m currently running 1.7.10 mainline straight from the nginx.org
repository.
We are hosting an application that needs to be accessible to Internet
Explorer users, in addition to all other normal browsers.

tl;dr: I want do have an add_header inside an if {}. nginx 1.7.10 won’t
let me.

I’m trying to add the following header, which WORKS JUST FINE in all
other browser but IE:

server {

add_header Content-Security-Policy "
default-src ‘self’ https://.example.nl https://.example.net;
connect-src ‘self’ https://.example.nl https://.example.net;
font-src ‘self’ data: https://.example.nl
https://
.example.net;
script-src ‘self’ ‘unsafe-inline’ ‘unsafe-eval’
https://.example.nl https://.example.net;
style-src ‘self’ ‘unsafe-inline’;
img-src ‘self’ data: https://.example.nl
https://
.example.net;
frame-src ‘self’;
object-src ‘self’ ‘unsafe-inline’;
";

}

In Chrome and Firefox, this works like a charm. But Internet Explorer
goes absolutely haywire on it.
According to http://content-security-policy.com/ … Internet Explorer 10
has limited support for X-Content-Security-Policy, and no IE has support
for Content-Security-Policy.

In reality, that’s not really true. I found that accessing the site with
IE11, results in a badly rendered page that could be classified as “not
working”.
Remove the header, and everything works absolutely fine in IE11.

If I load the page in IE11 and hit F12, then change it to MS10
compatibility, it throws a DNS error. Yes, I kid you not, DNS.
Remove the header, and everything works absolutely fine in IE10
compatibility mode.

In an attempt to keep the header for all other browsers but MSIE, I
wanted to do the following instead:

server {

if ($http_user_agent ~ MSIE ) {
add_header Content-Security-Policy "
default-src ‘self’ https://.example.nl https://.example.net;
connect-src ‘self’ https://.example.nl https://.example.net;
font-src ‘self’ data: https://.example.nl
https://
.example.net;
script-src ‘self’ ‘unsafe-inline’ ‘unsafe-eval’
https://.example.nl https://.example.net;
style-src ‘self’ ‘unsafe-inline’;
img-src ‘self’ data: https://.example.nl
https://
.example.net;
frame-src ‘self’;
object-src ‘self’ ‘unsafe-inline’;
";
}
}

According to both If is Evil… when used in location context | NGINX and
Module ngx_http_headers_module (see Context
of add_header), it should be allowed inside an if.
But yet:

root:~# nginx -t
nginx: [emerg] “add_header” directive is not allowed here in
/etc/nginx/sites-enabled/webtv-test:37
nginx: configuration file /etc/nginx/nginx.conf test failed
root:~#

What am I doing wrong, if anything? And if I can avoid using “if” like
that, I’d obviously prefer that.

Kind regards,

Danil

Hi again,

And ugh, yet again realising what I did wrong right after hitting
“send”:

Danil Mostertman schreef op 18-2-2015 om 17:57:

tl;dr: I want do have an add_header inside an if {}. nginx 1.7.10
won’t let me.
Because I didn’t put the if inside a location.

What am I doing wrong, if anything? And if I can avoid using “if” like
that, I’d obviously prefer that.

Answering my own question: “add_header” can only be inside an “if”
that’s inside a “location”.
I have no “location” for the root, so I figured it could be inside
“server”.

Danil

On Wednesday 18 February 2015 17:57:13 Danil Mostertman wrote:
[…]

What am I doing wrong, if anything? And if I can avoid using “if” like
that, I’d obviously prefer that.

You can avoid it by using the map directive and a variable
as the add_header value.

Like this:

map $http_user_agent $csp {
~MSIE “”;
default "
default-src ‘self’ https://.example.nl https://.example.net;
connect-src ‘self’ https://.example.nl https://.example.net;
font-src ‘self’ data: https://.example.nl
https://
.example.net;
script-src ‘self’ ‘unsafe-inline’ ‘unsafe-eval’
https://.example.nl https://.example.net;
style-src ‘self’ ‘unsafe-inline’;
img-src ‘self’ data: https://.example.nl
https://
.example.net;
frame-src ‘self’;
object-src ‘self’ ‘unsafe-inline’;
";
}

add_header Content-Security-Policy $csp;

wbr, Valentin V. Bartenev