Behavior of security headers

Hi,

I’ve a question regarding the different security headers
(Content-Security-Policy, etc.) which can be set via add_header.
In the docs it is mentioned that “add_header” can be set on every level
(http, server, location). So i tried to set some security related header
in
the server block related to one domain. But this did not work as
expected -
in detail it did not work at all. Even the “Strict-Transport-Security”
header did not work on server level…

My first guess was that the used nginx version (1.6.2 stable) may have
some
problems… So I’ve updated to 1.7.9 from mainline repo. But nothing
changed…

After some resultless googling for this problem I tried a lot of
combinations and found that all headers work on only on location level -
which confused me. In my opinion these headers shall work on server
level as
well or do I misunderstand something in these mechanisms?

config of my first try (NOT working)
server {
add_header Strict-Transport-Security “max-age=31536000;
includeSubdomains; preload;”;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options “nosniff”;
add_header X-XSS-Protection “1; mode=block”;
add_header Content-Security-Policy “default-src ‘none’; script-src
‘self’
‘unsafe-inline’ ‘unsafe-eval’ https:; connect-src ‘self’ https:; img-src
‘self’ https:; style-src ‘self’ ‘unsafe-inline’ https:; font-src ‘self’
https:; frame-src ‘self’ https:; object-src ‘none’;”;

location / …
}

config of confused last try (WORKS)
server {

location / {
add_header Strict-Transport-Security “max-age=31536000;
includeSubdomains; preload;”;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options “nosniff”;
add_header X-XSS-Protection “1; mode=block”;
add_header Content-Security-Policy “default-src ‘none’; script-src
‘self’ ‘unsafe-inline’ ‘unsafe-eval’ https:; connect-src ‘self’ https:;
img-src ‘self’ https:; style-src ‘self’ ‘unsafe-inline’ https:; font-src
‘self’ https:; frame-src ‘self’ https:; object-src ‘none’;”;
}
}

And btw. yes - I’ve restarted nginx after each config change and also
emptied my browser cache before inspecting the headers.

Thanks for help and enlightenment :slight_smile:
Oliver

Posted at Nginx Forum:

On Monday 26 January 2015 06:19:54 okamzol wrote:

My first guess was that the used nginx version (1.6.2 stable) may have some
problems… So I’ve updated to 1.7.9 from mainline repo. But nothing
changed…

After some resultless googling for this problem I tried a lot of
combinations and found that all headers work on only on location level -
which confused me. In my opinion these headers shall work on server level as
well or do I misunderstand something in these mechanisms?
[…]

I guess this sentence from the documentation can shed light on your
problem:

| These directives are inherited from the previous level if and only if
| there are no add_header directives defined on the current level.

http://nginx.org/r/add_header

wbr, Valentin V. Bartenev

That’s exactly the point - I wanted to set these headers on server level
to
become valid for the whole domain and all inherent location blocks. This
avoids the need to repeat all headers in each location…

Posted at Nginx Forum:

On Monday 26 January 2015 08:38:08 okamzol wrote:

That’s exactly the point - I wanted to set these headers on server level to
become valid for the whole domain and all inherent location blocks. This
avoids the need to repeat all headers in each location…

But are you sure, that you don’t have add_header directives in your
location
blocks at the same time?

Please note:

server {
add_header X-Header-One one;
add_header X-Header-Two two;

   location / {
       add_header X-Header-Three three;
   }

}

in the configuration above only the X-Header-Three will be added to
response.

wbr, Valentin V. Bartenev

Hello,

I guess the ‘problem’ you are struggling with is one you seem to inflict
to
yourself.

As Valentin explained, and as it is the case with other directives as
well (
fastcgi_param
http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_param
immediately comes to my mind), if you specify some add_header
http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header
directives at a certain level, it will cut-off the default inheritance
property, effectively not applying add_header directives defined at
upper
levels.

The real question here is:
Why do you wanna avoid duplicating the common add_header fields over all
the locations?
The obvious answer being the ‘ease’ of maintenance is maybe flawed:

  1. Two years later, to know the configuration applied to a location
    by a
    certain directive, you would need to look at several places. If you
    forgot
    you put some at server levels, you might end up with ‘strange’
    behaviors.
    Even more true if the maintenance is done by someone else…
  2. If you want to replace the configuration of a directive amongst
    all
    locations where it is defined, standard Linux (UNIX?) commands such
    as
    grep, sed, cut, awk, etc. are there to handle such repetitive job.
  3. Finally, generating similar or identical copies of the same blocks
    on
    high volumes is generally not done by hand, but rather with tools
    such as
    configuration management ones.

I suggest you watch the video ‘Scalable configuration’ from Igor S.
https://youtu.be/YWRYbLKsS0I, recorded during the nginx user
conference
from last year: that would maybe help you understand better what I
attempted to explain here.

What you sometimes think is a problem might actually save you from
actually
getting into trouble without even noticing it…
What is ‘unefficient’ to human eyes might be ‘irrelevant’
machine-wise…
reverse might also be true. :o)

B. R.

OK, if I understand this right - in my original config I have 2
additional
add_header (cache-control) directives in /image location. And these 2
directives prevent that the security headers will be applied on server
level? It seems so as this will explain why it works when I apply the
sec.headers on location level…

But how to handle domain-wide headers like those security headers and
location specific ones like cache-control? I mean, without repeating all
securty headers in each location?

Posted at Nginx Forum: