Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Nginx configuration for CORS-enabled HTTPS proxy with origin white-list defined by a simple regex
# Acts as a nginx HTTPS proxy server
# enabling CORS only to domains matched by regex
# /https?://.*\.mckinsey\.com(:[0-9]+)?)/
# Based on:
# *
# *
server {
listen 443 default_server ssl;
server_name localhost;
# Fake certs - fine for development purposes :-)
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
ssl_session_timeout 5m;
location / {
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Nginx doesn't support nested If statements, so we
# concatenate compound conditions on the $cors variable
# and process later
# If request comes from allowed subdomain
# (* then we enable CORS
if ($http_origin ~* (https?://.*\.mckinsey\.com(:[0-9]+)?$)) {
set $cors "1";
# OPTIONS indicates a CORS pre-flight request
if ($request_method = 'OPTIONS') {
set $cors "${cors}o";
# Append CORS headers to any request from
# allowed CORS domain, except OPTIONS
if ($cors = "1") {
more_set_headers 'Access-Control-Allow-Origin: $http_origin';
more_set_headers 'Access-Control-Allow-Credentials: true';
proxy_pass http://serverIP:serverPort;
# OPTIONS (pre-flight) request from allowed
# CORS domain. return response directly
if ($cors = "1o") {
more_set_headers 'Access-Control-Allow-Origin: $http_origin';
more_set_headers 'Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE';
more_set_headers 'Access-Control-Allow-Credentials: true';
more_set_headers 'Access-Control-Allow-Headers: Origin,Content-Type,Accept';
add_header Content-Length 0;
add_header Content-Type text/plain;
return 204;
# Requests from non-allowed CORS domains
proxy_pass http://serverIP:serverPort;
Copy link

studious commented Mar 30, 2016

That covers an optional port in the url

Copy link

boltgolt commented Nov 19, 2016

I believe will also match the $http_origin regex check, might be an security issue.

Copy link

plrunner commented Nov 24, 2016

Good work, really, thank you.

Copy link

cchang62 commented Jan 25, 2017

Thanks for sharing.

Copy link

genomics-geek commented Feb 27, 2017

Does anyone know how to get add_header on RHEL7? Seems like I can't install the nginx extras needed for this to work

Copy link

gantaa commented Apr 4, 2017

Here is the regex that does NOT match security flaw proposed by @boltgolt, but still matches desired domains:


Copy link

gopal-g commented Aug 15, 2017

I am running nginix 1.11.9 and i get the error : unknown directive more_set_headers, I am actually working on vagrant environment with laravel homestead platform hence i am also not sure if this configuration change needs to be updated every time i reload the vagrant. this is my first project on vagrant/homestead.


I ran sudo apt-get install nginx-extras
restarted nginx - its working just fine

and i even rebooted the vagrant to see if i will lose the changes luckily i didn't thank you very much for this. I am using this script to allow CORS for a angular app satellizer as front-end client with laravel as backend just in case any one is wondering if they can use it for the one of these :) Thank you.

Copy link

fkoksal commented Sep 27, 2017

Here is the regex that worked for me:

  • matches both http and https
  • matches with or without subdomains
  • does not match

Copy link

ZeusMode commented Sep 29, 2017

for those who are having problems with more_set_headers, you should use add_header.

PS: add_header need 2 params
add_header 'Access-Control-Allow-Credentials' 'true';

Copy link

anastasiosyal commented Mar 9, 2018

Security by regex, will always be weak. Here's another expression that will bypass the 'fixed' version of the regex:
There's probably more attack vectors even if you did expand the regex to include the hash exclusion as below

Copy link

cholnhial commented Jun 25, 2018

Thank you so much, this was helpful.

Copy link

neskhodovskiy commented Aug 31, 2018

@anastasiosyal you are right. The most secure regex will at least look something like


Test on regex101

Since hostname parts cannot contain anything except alphanumeric characters and dash RFC 952.

Copy link

opsarno commented Nov 9, 2018

Why don't we define $http_origin ?
Access nginx website ,I don't see this variable.

Copy link

opsarno commented Nov 13, 2018

If use https request, the $http_origin it's invalid.

Copy link

julioaze commented Nov 30, 2018

Hey there. Where should I use this code? Please

Copy link

cvbuelow commented Jan 5, 2019

Not sure why you people are concerned about the regex security when using $http_origin. This variable will not include any path info so you don't have to worry about ? and #.

Copy link

iki commented Sep 15, 2019

Thanks for inspiration. Here's what we use with added exposed headers:

Copy link

libmw commented Aug 12, 2021

Not sure why you people are concerned about the regex security when using $http_origin. This variable will not include any path info so you don't have to worry about ? and #.

Yeah,I think so!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment