Skip to content

Commit 85c6018

Browse files
committed
Ability to control Referrer-Policy header #2
1 parent 48a8a7a commit 85c6018

File tree

3 files changed

+137
-16
lines changed

3 files changed

+137
-16
lines changed

README.md

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,14 @@ Accept-Ranges: bytes
2323
Connection: keep-alive
2424
X-Frame-Options: SAMEORIGIN <-----------
2525
X-XSS-Protection: 1; mode=block <-----------
26+
Referrer-Policy: no-referrer-when-downgrade <-----------
2627
```
2728

28-
Running `curl -IL http://example.com/some.css` (or `some.js`) will yield additional headers:
29+
Running `curl -IL http://example.com/some.css` (or `some.js`) will yield *additional* security header:
2930

3031
```
3132
HTTP/1.1 200 OK
32-
Server: nginx
33-
Date: Tue, 21 May 2019 16:15:46 GMT
34-
Content-Type: text/css; charset=UTF-8
35-
Vary: Accept-Encoding
36-
Accept-Ranges: bytes
37-
Connection: keep-alive
38-
X-Frame-Options: SAMEORIGIN <-----------
39-
X-XSS-Protection: 1; mode=block <-----------
33+
...
4034
X-Content-Type-Options: nosniff <-----------
4135
```
4236

@@ -62,6 +56,7 @@ Enables or disables applying security headers. The default set includes:
6256

6357
* `X-Frame-Options: SAMEORIGIN`
6458
* `X-XSS-Protection: 1; mode=block`
59+
* `Referrer-Policy: strict-origin-when-cross-origin`
6560
* `X-Content-Type-Options: nosniff` (for CSS and Javascript)
6661

6762
The values of these headers (or their inclusion) can be controlled with other `security_headers_*` directives below.
@@ -77,24 +72,38 @@ Enables hiding headers which leak software information:
7772
* `Server`
7873
* `X-Powered-By`
7974

75+
Next are the common security headers being set. It's worth noting that special value of `omit` for directives below
76+
will disable sending a particular header by the module (useful if you want to let your backend app to send it).
77+
8078
### `security_headers_xss`
8179

8280
- **syntax**: `security_headers off | on | block | omit`
8381
- **default**: `block`
8482
- **context**: `http`, `server`, `location`
8583

8684
Controls `X-XSS-Protection` header.
87-
Special `omit` value will disable sending the header.
85+
Special `omit` value will disable sending the header by the module.
8886
The `off` value is for disabling XSS protection: `X-XSS-Protection: 0`.
8987

9088
### `security_headers_frame`
9189

92-
- **syntax**: `security_headers_frames sameorigin | deny | omit`
90+
- **syntax**: `security_headers_frame sameorigin | deny | omit`
9391
- **default**: `sameorigin`
9492
- **context**: `http`, `server`, `location`
9593

9694
Controls inclusion and value of `X-Frame-Options` header.
97-
Special `omit` value will disable sending the header.
95+
Special `omit` value will disable sending the header by the module.
96+
97+
98+
### `security_headers_referrer_policy`
99+
100+
- **syntax**: `security_headers_referrer_policy no-referrer | no-referrer-when-downgrade | same-origin | origin
101+
| strict-origin | origin-when-cross-origin | strict-origin-when-cross-origin | unsafe-url | omit`
102+
- **default**: `no-referrer-when-downgrade`
103+
- **context**: `http`, `server`, `location`
104+
105+
Controls inclusion and value of [`Referrer-Policy`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy) header.
106+
Special `omit` value will disable sending the header by the module.
98107

99108
### `security_headers_nosniff_types`
100109

src/ngx_http_security_headers_module.c

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,25 @@
1616
#define NGX_HTTP_FO_HEADER_SAME 1
1717
#define NGX_HTTP_FO_HEADER_DENY 2
1818

19+
/* The Referrer Policy header */
20+
#define NGX_HTTP_RP_HEADER_NO 1
21+
#define NGX_HTTP_RP_HEADER_DOWNGRADE 2
22+
#define NGX_HTTP_RP_HEADER_SAME_ORIGIN 3
23+
#define NGX_HTTP_RP_HEADER_ORIGIN 4
24+
#define NGX_HTTP_RP_HEADER_STRICT_ORIGIN 5
25+
#define NGX_HTTP_RP_HEADER_ORIGIN_WHEN_CROSS 6
26+
#define NGX_HTTP_RP_HEADER_STRICT_ORIG_WHEN_CROSS 7
27+
#define NGX_HTTP_RP_HEADER_UNSAFE_URL 8
28+
29+
1930

2031
typedef struct {
2132
ngx_flag_t enable;
2233
ngx_flag_t hide_server_tokens;
2334

2435
ngx_uint_t xss;
2536
ngx_uint_t fo;
37+
ngx_uint_t rp;
2638

2739
ngx_hash_t nosniff_types;
2840
ngx_array_t *types_keys;
@@ -44,6 +56,34 @@ static ngx_conf_enum_t ngx_http_frame_options[] = {
4456
{ ngx_null_string, 0 }
4557
};
4658

59+
static ngx_conf_enum_t ngx_http_referrer_policy[] = {
60+
{ ngx_string("no-referrer"),
61+
NGX_HTTP_RP_HEADER_NO },
62+
63+
{ ngx_string("no-referrer-when-downgrade"),
64+
NGX_HTTP_RP_HEADER_DOWNGRADE },
65+
66+
{ ngx_string("same-origin"),
67+
NGX_HTTP_RP_HEADER_SAME_ORIGIN },
68+
69+
{ ngx_string("origin"),
70+
NGX_HTTP_RP_HEADER_ORIGIN },
71+
72+
{ ngx_string("strict-origin"),
73+
NGX_HTTP_RP_HEADER_STRICT_ORIGIN },
74+
75+
{ ngx_string("origin-when-cross-origin"),
76+
NGX_HTTP_RP_HEADER_ORIGIN_WHEN_CROSS },
77+
78+
{ ngx_string("unsafe-url"),
79+
NGX_HTTP_RP_HEADER_UNSAFE_URL },
80+
81+
{ ngx_string("omit"),
82+
NGX_HTTP_SECURITY_HEADER_OMIT },
83+
84+
{ ngx_null_string, 0 }
85+
};
86+
4787
static ngx_int_t ngx_http_security_headers_filter(ngx_http_request_t *r);
4888
static void *ngx_http_security_headers_create_loc_conf(ngx_conf_t *cf);
4989
static char *ngx_http_security_headers_merge_loc_conf(ngx_conf_t *cf,
@@ -96,6 +136,13 @@ static ngx_command_t ngx_http_security_headers_commands[] = {
96136
offsetof(ngx_http_security_headers_loc_conf_t, fo),
97137
ngx_http_frame_options },
98138

139+
{ ngx_string("security_headers_referrer_policy"),
140+
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
141+
ngx_conf_set_enum_slot,
142+
NGX_HTTP_LOC_CONF_OFFSET,
143+
offsetof(ngx_http_security_headers_loc_conf_t, rp),
144+
ngx_http_referrer_policy },
145+
99146
ngx_null_command
100147
};
101148

@@ -220,9 +267,27 @@ ngx_http_security_headers_filter(ngx_http_request_t *r)
220267
}
221268

222269
/* Referrer-Policy: no-referrer-when-downgrade */
223-
if (r->headers_out.status != NGX_HTTP_NOT_MODIFIED) {
224-
ngx_str_set(&key, "Referrer-Policy");
225-
ngx_str_set(&val, "no-referrer-when-downgrade");
270+
if (r->headers_out.status != NGX_HTTP_NOT_MODIFIED
271+
&& NGX_HTTP_SECURITY_HEADER_OMIT != slcf->rp) {
272+
ngx_str_set(&key, "Referrer-Policy");
273+
274+
if (NGX_HTTP_RP_HEADER_NO == slcf->rp) {
275+
ngx_str_set(&val, "no-referrer");
276+
} else if (NGX_HTTP_RP_HEADER_DOWNGRADE == slcf->rp) {
277+
ngx_str_set(&val, "no-referrer-when-downgrade");
278+
} else if (NGX_HTTP_RP_HEADER_SAME_ORIGIN == slcf->rp) {
279+
ngx_str_set(&val, "same-origin");
280+
} else if (NGX_HTTP_RP_HEADER_ORIGIN == slcf->rp) {
281+
ngx_str_set(&val, "origin");
282+
} else if (NGX_HTTP_RP_HEADER_STRICT_ORIGIN == slcf->rp) {
283+
ngx_str_set(&val, "strict-origin");
284+
} else if (NGX_HTTP_RP_HEADER_ORIGIN_WHEN_CROSS == slcf->rp) {
285+
ngx_str_set(&val, "origin-when-cross-origin");
286+
} else if (NGX_HTTP_RP_HEADER_STRICT_ORIG_WHEN_CROSS == slcf->rp) {
287+
ngx_str_set(&val, "strict-origin-when-cross-origin");
288+
} else if (NGX_HTTP_RP_HEADER_UNSAFE_URL == slcf->rp) {
289+
ngx_str_set(&val, "unsafe-url");
290+
}
226291
ngx_set_headers_out_by_search(r, &key, &val);
227292
}
228293

@@ -245,6 +310,7 @@ ngx_http_security_headers_create_loc_conf(ngx_conf_t *cf)
245310

246311
conf->xss = NGX_CONF_UNSET_UINT;
247312
conf->fo = NGX_CONF_UNSET_UINT;
313+
conf->rp = NGX_CONF_UNSET_UINT;
248314
conf->enable = NGX_CONF_UNSET;
249315
conf->hide_server_tokens = NGX_CONF_UNSET_UINT;
250316

@@ -275,6 +341,8 @@ ngx_http_security_headers_merge_loc_conf(ngx_conf_t *cf, void *parent,
275341
NGX_HTTP_XSS_HEADER_BLOCK);
276342
ngx_conf_merge_uint_value(conf->fo, prev->fo,
277343
NGX_HTTP_FO_HEADER_SAME);
344+
ngx_conf_merge_uint_value(conf->rp, prev->rp,
345+
NGX_HTTP_RP_HEADER_STRICT_ORIG_WHEN_CROSS);
278346

279347
return NGX_CONF_OK;
280348
}

t/headers.t

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,4 +96,48 @@ hello world
9696
!x-content-type-options
9797
x-frame-options: SAMEORIGIN
9898
!Server
99-
Referrer-Policy: no-referrer-when-downgrade
99+
Referrer-Policy: strict-origin-when-cross-origin
100+
101+
102+
103+
=== TEST 6: custom referrer-policy
104+
--- config
105+
security_headers on;
106+
security_headers_referrer_policy unsafe-url;
107+
location = /hello {
108+
return 200 "hello world\n";
109+
}
110+
--- request
111+
GET /hello
112+
--- response_body
113+
hello world
114+
--- response_headers
115+
!x-content-type-options
116+
x-frame-options: SAMEORIGIN
117+
x-xss-protection: 1; mode=block
118+
referrer-policy: unsafe-url
119+
120+
121+
122+
=== TEST 7: co-exist with add header for custom referrer-policy
123+
--- config
124+
security_headers on;
125+
security_headers_referrer_policy omit;
126+
127+
location = /hello {
128+
return 200 "hello world\n";
129+
add_header 'Referrer-Policy' 'origin';
130+
}
131+
location = /hello-proxied {
132+
proxy_buffering off;
133+
proxy_pass http://127.0.0.1:$TEST_NGINX_SERVER_PORT/hello;
134+
}
135+
--- request
136+
GET /hello-proxied
137+
--- response_body
138+
hello world
139+
--- response_headers
140+
!x-content-type-options
141+
x-frame-options: SAMEORIGIN
142+
x-xss-protection: 1; mode=block
143+
referrer-policy: origin

0 commit comments

Comments
 (0)