Skip to content

Commit 8fea521

Browse files
committed
Add X-Content-Type-Options for all responses
1 parent 493261b commit 8fea521

4 files changed

Lines changed: 25 additions & 59 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Changelog
2+
All notable changes to this project will be documented in this file.
3+
4+
## [0.0.10] - 2020-05-31
5+
### Changed
6+
* `X-Content-Type-Options` is now sent for all resources to accomodate Chromium's CORB
7+
(see [webhint.io #1221](https://github.com/webhintio/hint/issues/1221))
8+

README.md

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ http {
1111
}
1212
```
1313

14-
Running `curl -IL https://example.com/` will yield additional headers:
14+
Running `curl -IL https://example.com/` will yield the added security headers:
1515

1616
<pre>
1717
HTTP/1.1 200 OK
@@ -22,31 +22,23 @@ Vary: Accept-Encoding
2222
Accept-Ranges: bytes
2323
Connection: keep-alive
2424
<b>X-Frame-Options: SAMEORIGIN
25+
X-Content-Type-Options: nosniff
2526
X-XSS-Protection: 1; mode=block
2627
Referrer-Policy: strict-origin-when-cross-origin
2728
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload</b>
2829
</pre>
2930

30-
Running `curl -IL https://example.com/some.css` (or `some.js`) will yield *additional* security header:
31-
32-
<pre>
33-
HTTP/1.1 200 OK
34-
...
35-
<b>X-Content-Type-Options: nosniff</b>
36-
</pre>
37-
3831
In general, the module features sending security HTTP headers in a way that better conforms to the standards.
3932
For instance, `Strict-Transport-Security` header should *not* be sent for plain HTTP requests.
4033
The module follows this recommendation.
4134

4235
## Key Features
4336

4437
* Plug-n-Play: the default set of security headers can be enabled with `security_headers on;` in your NGINX configuration
45-
* Sends `X-Content-Type-Options` only for relevant MIME types (CSS/JS), preserving unnecessary headers from being sent for HTML documents
46-
* Similarly, sends HTML-only security headers for relevant types only, not sending for others, e.g. `X-Frame-Options` is useless for CSS
38+
* Sends HTML-only security headers for relevant types only, not sending for others, e.g. `X-Frame-Options` is useless for CSS
4739
* Plays well with conditional `GET` requests: the security headers are not included there unnecessarily
4840
* Does not suffer the `add_header` directive's pitfalls
49-
* Hides `X-Powered-By`, which often leaks PHP version information
41+
* Hides `X-Powered-By` and other headers which often leak software version information
5042
* Hides `Server` header altogether, not just the version information
5143

5244
## Configuration directives
@@ -62,7 +54,7 @@ Enables or disables applying security headers. The default set includes:
6254
* `X-Frame-Options: SAMEORIGIN`
6355
* `X-XSS-Protection: 1; mode=block`
6456
* `Referrer-Policy: strict-origin-when-cross-origin`
65-
* `X-Content-Type-Options: nosniff` (for CSS and Javascript)
57+
* `X-Content-Type-Options: nosniff`
6658

6759
The values of these headers (or their inclusion) can be controlled with other `security_headers_*` directives below.
6860

@@ -84,7 +76,7 @@ It's worth noting that some of those headers bear functional use, e.g. [`X-Page-
8476
> ... it is used to prevent infinite loops and unnecessary rewrites when PageSpeed
8577
> fetches resources from an origin that also uses PageSpeed
8678
87-
So it's best to specify `hide_server_tokens on;` in a front-facing NGINX insances, e.g.
79+
So it's best to specify `hide_server_tokens on;` in a front-facing NGINX instances, e.g.
8880
the one being accessed by actual browsers, and not the ones consumed by Varnish or other software.
8981

9082
In most cases you will be just fine with `security_headers on;` and `hide_server_tokens on;`, without any adjustments.
@@ -122,23 +114,15 @@ Special `omit` value will disable sending the header by the module.
122114
Controls inclusion and value of [`Referrer-Policy`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy) header.
123115
Special `omit` value will disable sending the header by the module.
124116

125-
### `security_headers_nosniff_types`
126-
127-
- **syntax**: `security_headers_nosniff_types <mime_type> [..]`
128-
- **default**: `text/css text/javascript application/javascript`
129-
- **context**: `http`, `server`, `location`
130-
131-
Defines MIME types, for which `X-Content-Type-Options: nosniff` is sent.
132-
133117
## Install
134118

135-
### CentOS/RHEL 6, 7, 8
119+
### CentOS/RHEL 6, 7, 8 or Amazon Linux 2
136120

137-
It's easy to install the module in your stable nginx instance dynamically:
121+
It's easy to install the module in your stable NGINX instance dynamically:
138122

139123
```bash
140124
sudo yum -y install https://extras.getpagespeed.com/release-latest.rpm
141-
sudo yum install nginx-module-security-headers
125+
sudo yum -y install nginx-module-security-headers
142126
```
143127

144128
Then add it at the top of your `nginx.conf`:

src/ngx_http_security_headers_module.c

Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,6 @@ typedef struct {
3636
ngx_uint_t fo;
3737
ngx_uint_t rp;
3838

39-
ngx_hash_t nosniff_types;
40-
ngx_array_t *nosniff_types_keys;
41-
4239
ngx_hash_t text_types;
4340
ngx_array_t *text_types_keys;
4441

@@ -95,13 +92,6 @@ static ngx_int_t ngx_http_security_headers_init(ngx_conf_t *cf);
9592
static ngx_int_t ngx_set_headers_out_by_search(ngx_http_request_t *r,
9693
ngx_str_t *key, ngx_str_t *value);
9794

98-
ngx_str_t ngx_http_security_headers_default_nosniff_types[] = {
99-
ngx_string("text/css"),
100-
ngx_string("text/javascript"),
101-
ngx_string("application/javascript"),
102-
ngx_null_string
103-
};
104-
10595
ngx_str_t ngx_http_security_headers_default_text_types[] = {
10696
ngx_string("text/html"),
10797
ngx_string("application/xhtml+xml"),
@@ -126,13 +116,6 @@ static ngx_command_t ngx_http_security_headers_commands[] = {
126116
offsetof(ngx_http_security_headers_loc_conf_t, hide_server_tokens ),
127117
NULL },
128118

129-
{ ngx_string("security_headers_nosniff_types"),
130-
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
131-
ngx_http_types_slot,
132-
NGX_HTTP_LOC_CONF_OFFSET,
133-
offsetof(ngx_http_security_headers_loc_conf_t, nosniff_types_keys),
134-
&ngx_http_security_headers_default_nosniff_types[0] },
135-
136119
{ ngx_string("security_headers_xss"),
137120
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
138121
ngx_conf_set_enum_slot,
@@ -249,9 +232,7 @@ ngx_http_security_headers_filter(ngx_http_request_t *r)
249232
}
250233

251234
/* add X-Content-Type-Options to output */
252-
if (r->headers_out.status == NGX_HTTP_OK
253-
&& ngx_http_test_content_type(r, &slcf->nosniff_types) != NULL)
254-
{
235+
if (r->headers_out.status == NGX_HTTP_OK) {
255236
ngx_str_set(&key, "X-Content-Type-Options");
256237
ngx_str_set(&val, "nosniff");
257238

@@ -275,7 +256,8 @@ ngx_http_security_headers_filter(ngx_http_request_t *r)
275256
}
276257

277258
#if (NGX_HTTP_SSL)
278-
if (r->connection->ssl) {
259+
if (r->connection->ssl)
260+
{
279261
ngx_str_set(&key, "Strict-Transport-Security");
280262
ngx_str_set(&val, "max-age=63072000; includeSubDomains; preload");
281263
ngx_set_headers_out_by_search(r, &key, &val);
@@ -359,14 +341,6 @@ ngx_http_security_headers_merge_loc_conf(ngx_conf_t *cf, void *parent,
359341
ngx_conf_merge_value(conf->hide_server_tokens,
360342
prev->hide_server_tokens, 0 );
361343

362-
if (ngx_http_merge_types(cf, &conf->nosniff_types_keys, &conf->nosniff_types,
363-
&prev->nosniff_types_keys, &prev->nosniff_types,
364-
ngx_http_security_headers_default_nosniff_types)
365-
!= NGX_OK)
366-
{
367-
return NGX_CONF_ERROR;
368-
}
369-
370344
if (ngx_http_merge_types(cf, &conf->text_types_keys, &conf->text_types,
371345
&prev->text_types_keys, &prev->text_types,
372346
ngx_http_security_headers_default_text_types)

t/headers.t

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ hello world
3333
hello world
3434
--- response_headers
3535
content-type: text/plain; charset=utf-8
36-
!x-content-type-options
36+
x-content-type-options: nosniff
3737
x-frame-options: SAMEORIGIN
3838
x-xss-protection: 1; mode=block
3939
@@ -72,7 +72,7 @@ x-content-type-options: nosniff
7272
--- response_body
7373
hello world
7474
--- response_headers
75-
!x-content-type-options
75+
x-content-type-options: nosniff
7676
x-frame-options: SAMEORIGIN
7777
!server
7878
@@ -95,7 +95,7 @@ x-frame-options: SAMEORIGIN
9595
--- response_body
9696
hello world
9797
--- response_headers
98-
!x-content-type-options
98+
x-content-type-options: nosniff
9999
x-frame-options: SAMEORIGIN
100100
!Server
101101
Referrer-Policy: strict-origin-when-cross-origin
@@ -114,7 +114,7 @@ Referrer-Policy: strict-origin-when-cross-origin
114114
--- response_body
115115
hello world
116116
--- response_headers
117-
!x-content-type-options
117+
x-content-type-options: nosniff
118118
x-frame-options: SAMEORIGIN
119119
x-xss-protection: 1; mode=block
120120
referrer-policy: unsafe-url
@@ -139,7 +139,7 @@ referrer-policy: unsafe-url
139139
--- response_body
140140
hello world
141141
--- response_headers
142-
!x-content-type-options
142+
x-content-type-options: nosniff
143143
x-frame-options: SAMEORIGIN
144144
x-xss-protection: 1; mode=block
145145
referrer-policy: origin

0 commit comments

Comments
 (0)