2727#define NGX_HTTP_RP_HEADER_STRICT_ORIG_WHEN_CROSS 7
2828#define NGX_HTTP_RP_HEADER_UNSAFE_URL 8
2929
30+ /* Cross-Origin-Opener-Policy header */
31+ #define NGX_HTTP_COOP_HEADER_UNSAFE_NONE 1
32+ #define NGX_HTTP_COOP_HEADER_SAME_ORIGIN_POPUPS 2
33+ #define NGX_HTTP_COOP_HEADER_SAME_ORIGIN 3
34+
35+ /* Cross-Origin-Resource-Policy header */
36+ #define NGX_HTTP_CORP_HEADER_SAME_SITE 1
37+ #define NGX_HTTP_CORP_HEADER_SAME_ORIGIN 2
38+ #define NGX_HTTP_CORP_HEADER_CROSS_ORIGIN 3
39+
40+ /* Cross-Origin-Embedder-Policy header */
41+ #define NGX_HTTP_COEP_HEADER_UNSAFE_NONE 1
42+ #define NGX_HTTP_COEP_HEADER_REQUIRE_CORP 2
43+
3044typedef struct {
3145 ngx_flag_t enable ;
3246 ngx_flag_t hide_server_tokens ;
@@ -35,6 +49,9 @@ typedef struct {
3549 ngx_uint_t xss ;
3650 ngx_uint_t fo ;
3751 ngx_uint_t rp ;
52+ ngx_uint_t coop ;
53+ ngx_uint_t corp ;
54+ ngx_uint_t coep ;
3855
3956 ngx_hash_t text_types ;
4057 ngx_array_t * text_types_keys ;
@@ -113,6 +130,51 @@ static ngx_conf_enum_t ngx_http_referrer_policy[] = {
113130 { ngx_null_string , 0 }
114131};
115132
133+ static ngx_conf_enum_t ngx_http_cross_origin_opener_policy [] = {
134+ { ngx_string ("unsafe-none" ),
135+ NGX_HTTP_COOP_HEADER_UNSAFE_NONE },
136+
137+ { ngx_string ("same-origin-allow-popups" ),
138+ NGX_HTTP_COOP_HEADER_SAME_ORIGIN_POPUPS },
139+
140+ { ngx_string ("same-origin" ),
141+ NGX_HTTP_COOP_HEADER_SAME_ORIGIN },
142+
143+ { ngx_string ("omit" ),
144+ NGX_HTTP_SECURITY_HEADER_OMIT },
145+
146+ { ngx_null_string , 0 }
147+ };
148+
149+ static ngx_conf_enum_t ngx_http_cross_origin_resource_policy [] = {
150+ { ngx_string ("same-site" ),
151+ NGX_HTTP_CORP_HEADER_SAME_SITE },
152+
153+ { ngx_string ("same-origin" ),
154+ NGX_HTTP_CORP_HEADER_SAME_ORIGIN },
155+
156+ { ngx_string ("cross-origin" ),
157+ NGX_HTTP_CORP_HEADER_CROSS_ORIGIN },
158+
159+ { ngx_string ("omit" ),
160+ NGX_HTTP_SECURITY_HEADER_OMIT },
161+
162+ { ngx_null_string , 0 }
163+ };
164+
165+ static ngx_conf_enum_t ngx_http_cross_origin_embedder_policy [] = {
166+ { ngx_string ("unsafe-none" ),
167+ NGX_HTTP_COEP_HEADER_UNSAFE_NONE },
168+
169+ { ngx_string ("require-corp" ),
170+ NGX_HTTP_COEP_HEADER_REQUIRE_CORP },
171+
172+ { ngx_string ("omit" ),
173+ NGX_HTTP_SECURITY_HEADER_OMIT },
174+
175+ { ngx_null_string , 0 }
176+ };
177+
116178static ngx_int_t ngx_http_security_headers_filter (ngx_http_request_t * r );
117179static void * ngx_http_security_headers_create_loc_conf (ngx_conf_t * cf );
118180static char * ngx_http_security_headers_merge_loc_conf (ngx_conf_t * cf ,
@@ -173,6 +235,27 @@ static ngx_command_t ngx_http_security_headers_commands[] = {
173235 offsetof(ngx_http_security_headers_loc_conf_t , rp ),
174236 ngx_http_referrer_policy },
175237
238+ { ngx_string ("security_headers_coop" ),
239+ NGX_HTTP_MAIN_CONF |NGX_HTTP_SRV_CONF |NGX_HTTP_LOC_CONF |NGX_CONF_TAKE1 ,
240+ ngx_conf_set_enum_slot ,
241+ NGX_HTTP_LOC_CONF_OFFSET ,
242+ offsetof(ngx_http_security_headers_loc_conf_t , coop ),
243+ ngx_http_cross_origin_opener_policy },
244+
245+ { ngx_string ("security_headers_corp" ),
246+ NGX_HTTP_MAIN_CONF |NGX_HTTP_SRV_CONF |NGX_HTTP_LOC_CONF |NGX_CONF_TAKE1 ,
247+ ngx_conf_set_enum_slot ,
248+ NGX_HTTP_LOC_CONF_OFFSET ,
249+ offsetof(ngx_http_security_headers_loc_conf_t , corp ),
250+ ngx_http_cross_origin_resource_policy },
251+
252+ { ngx_string ("security_headers_coep" ),
253+ NGX_HTTP_MAIN_CONF |NGX_HTTP_SRV_CONF |NGX_HTTP_LOC_CONF |NGX_CONF_TAKE1 ,
254+ ngx_conf_set_enum_slot ,
255+ NGX_HTTP_LOC_CONF_OFFSET ,
256+ offsetof(ngx_http_security_headers_loc_conf_t , coep ),
257+ ngx_http_cross_origin_embedder_policy },
258+
176259 { ngx_string ("security_headers_text_types" ),
177260 NGX_HTTP_MAIN_CONF |NGX_HTTP_SRV_CONF |NGX_HTTP_LOC_CONF |NGX_CONF_1MORE ,
178261 ngx_http_types_slot ,
@@ -372,6 +455,75 @@ ngx_http_security_headers_filter(ngx_http_request_t *r)
372455 }
373456 }
374457
458+ /* Cross-Origin-Opener-Policy */
459+ if (r -> headers_out .status != NGX_HTTP_NOT_MODIFIED
460+ && NGX_HTTP_SECURITY_HEADER_OMIT != slcf -> coop ) {
461+
462+ switch (slcf -> coop ) {
463+ case NGX_HTTP_COOP_HEADER_UNSAFE_NONE :
464+ ngx_str_set (& val , "unsafe-none" );
465+ break ;
466+ case NGX_HTTP_COOP_HEADER_SAME_ORIGIN_POPUPS :
467+ ngx_str_set (& val , "same-origin-allow-popups" );
468+ break ;
469+ case NGX_HTTP_COOP_HEADER_SAME_ORIGIN :
470+ ngx_str_set (& val , "same-origin" );
471+ break ;
472+ default :
473+ val .len = 0 ;
474+ val .data = NULL ;
475+ }
476+ if (val .data ) {
477+ ngx_str_set (& key , "Cross-Origin-Opener-Policy" );
478+ ngx_set_headers_out_by_search (r , & key , & val );
479+ }
480+ }
481+
482+ /* Cross-Origin-Resource-Policy */
483+ if (r -> headers_out .status != NGX_HTTP_NOT_MODIFIED
484+ && NGX_HTTP_SECURITY_HEADER_OMIT != slcf -> corp ) {
485+
486+ switch (slcf -> corp ) {
487+ case NGX_HTTP_CORP_HEADER_SAME_SITE :
488+ ngx_str_set (& val , "same-site" );
489+ break ;
490+ case NGX_HTTP_CORP_HEADER_SAME_ORIGIN :
491+ ngx_str_set (& val , "same-origin" );
492+ break ;
493+ case NGX_HTTP_CORP_HEADER_CROSS_ORIGIN :
494+ ngx_str_set (& val , "cross-origin" );
495+ break ;
496+ default :
497+ val .len = 0 ;
498+ val .data = NULL ;
499+ }
500+ if (val .data ) {
501+ ngx_str_set (& key , "Cross-Origin-Resource-Policy" );
502+ ngx_set_headers_out_by_search (r , & key , & val );
503+ }
504+ }
505+
506+ /* Cross-Origin-Embedder-Policy */
507+ if (r -> headers_out .status != NGX_HTTP_NOT_MODIFIED
508+ && NGX_HTTP_SECURITY_HEADER_OMIT != slcf -> coep ) {
509+
510+ switch (slcf -> coep ) {
511+ case NGX_HTTP_COEP_HEADER_UNSAFE_NONE :
512+ ngx_str_set (& val , "unsafe-none" );
513+ break ;
514+ case NGX_HTTP_COEP_HEADER_REQUIRE_CORP :
515+ ngx_str_set (& val , "require-corp" );
516+ break ;
517+ default :
518+ val .len = 0 ;
519+ val .data = NULL ;
520+ }
521+ if (val .data ) {
522+ ngx_str_set (& key , "Cross-Origin-Embedder-Policy" );
523+ ngx_set_headers_out_by_search (r , & key , & val );
524+ }
525+ }
526+
375527
376528
377529 /* proceed to the next handler in chain */
@@ -392,6 +544,9 @@ ngx_http_security_headers_create_loc_conf(ngx_conf_t *cf)
392544 conf -> xss = NGX_CONF_UNSET_UINT ;
393545 conf -> fo = NGX_CONF_UNSET_UINT ;
394546 conf -> rp = NGX_CONF_UNSET_UINT ;
547+ conf -> coop = NGX_CONF_UNSET_UINT ;
548+ conf -> corp = NGX_CONF_UNSET_UINT ;
549+ conf -> coep = NGX_CONF_UNSET_UINT ;
395550 conf -> enable = NGX_CONF_UNSET ;
396551 conf -> hide_server_tokens = NGX_CONF_UNSET_UINT ;
397552 conf -> hsts_preload = NGX_CONF_UNSET_UINT ;
@@ -425,6 +580,12 @@ ngx_http_security_headers_merge_loc_conf(ngx_conf_t *cf, void *parent,
425580 NGX_HTTP_FO_HEADER_SAME );
426581 ngx_conf_merge_uint_value (conf -> rp , prev -> rp ,
427582 NGX_HTTP_RP_HEADER_STRICT_ORIG_WHEN_CROSS );
583+ ngx_conf_merge_uint_value (conf -> coop , prev -> coop ,
584+ NGX_HTTP_SECURITY_HEADER_OMIT );
585+ ngx_conf_merge_uint_value (conf -> corp , prev -> corp ,
586+ NGX_HTTP_SECURITY_HEADER_OMIT );
587+ ngx_conf_merge_uint_value (conf -> coep , prev -> coep ,
588+ NGX_HTTP_SECURITY_HEADER_OMIT );
428589
429590 return NGX_CONF_OK ;
430591}
0 commit comments