From 16ddc84d3fce9dfde9c284ee75f220816a9a5375 Mon Sep 17 00:00:00 2001 From: EdOverflow Date: Wed, 21 Dec 2016 17:22:45 +0100 Subject: [PATCH 1/5] Implement Content-Security-Policy (CSP) --- gratipay/security/__init__.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gratipay/security/__init__.py b/gratipay/security/__init__.py index 1f41550385..d6d363a5e8 100644 --- a/gratipay/security/__init__.py +++ b/gratipay/security/__init__.py @@ -40,3 +40,9 @@ def add_headers_to_response(response): # https://www.owasp.org/index.php/List_of_useful_HTTP_headers if 'X-XSS-Protection' not in response.headers: response.headers['X-XSS-Protection'] = '1; mode=block' + + # CSP - https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP + # Allow resources from gratipay.com & all gratipay subdomains. + # Allow fonts from cloud.typography.com. + if 'content-security-policy' not in response.headers: + response.headers['content-security-policy'] = 'default-src \'self\' *.gratipay.com; font-src cloud.typography.com;' From bd0c1d7ba4574aca3ac6182ddf62e018b2fb66f3 Mon Sep 17 00:00:00 2001 From: EdOverflow Date: Thu, 22 Dec 2016 11:16:50 +0100 Subject: [PATCH 2/5] Update CSP --- gratipay/security/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/gratipay/security/__init__.py b/gratipay/security/__init__.py index d6d363a5e8..de4981433d 100644 --- a/gratipay/security/__init__.py +++ b/gratipay/security/__init__.py @@ -45,4 +45,3 @@ def add_headers_to_response(response): # Allow resources from gratipay.com & all gratipay subdomains. # Allow fonts from cloud.typography.com. if 'content-security-policy' not in response.headers: - response.headers['content-security-policy'] = 'default-src \'self\' *.gratipay.com; font-src cloud.typography.com;' From bfb624aeac26ff122258630cc6ae293a2c3d9a1b Mon Sep 17 00:00:00 2001 From: EdOverflow Date: Thu, 22 Dec 2016 11:29:28 +0100 Subject: [PATCH 3/5] Fix IndentationError --- gratipay/security/__init__.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/gratipay/security/__init__.py b/gratipay/security/__init__.py index de4981433d..b265df32ae 100644 --- a/gratipay/security/__init__.py +++ b/gratipay/security/__init__.py @@ -45,3 +45,11 @@ def add_headers_to_response(response): # Allow resources from gratipay.com & all gratipay subdomains. # Allow fonts from cloud.typography.com. if 'content-security-policy' not in response.headers: + response.headers['content-security-policy'] = ( 'default-src \'self\';' + 'script-src assets.gratipay.com;' + 'style-src assets.gratipay.com;' + 'img-src *;' + 'font-src cloud.typography.com;' + 'upgrade-insecure-requests;' + 'block-all-mixed-content;' + 'reflected-xss block;') From 0d56128dd6e2c7b2eda7a36b7e6980f00d765b5e Mon Sep 17 00:00:00 2001 From: EdOverflow Date: Thu, 22 Dec 2016 15:49:08 +0100 Subject: [PATCH 4/5] Add test_ahtr_csp --- tests/py/test_security.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/py/test_security.py b/tests/py/test_security.py index eae24c24dd..1a15e6e628 100644 --- a/tests/py/test_security.py +++ b/tests/py/test_security.py @@ -53,6 +53,17 @@ def test_ahtr_sets_x_xss_protection(self): headers = self.client.GET('/about/').headers assert headers['X-XSS-Protection'] == '1; mode=block' + def test_ahtr__csp(self): + headers = self.client.GET('/about/').headers + assert headers['content-security-policy'] = ( 'default-src \'self\';' + 'script-src assets.gratipay.com;' + 'style-src assets.gratipay.com;' + 'img-src *;' + 'font-src cloud.typography.com;' + 'upgrade-insecure-requests;' + 'block-all-mixed-content;' + 'reflected-xss block;') + # ep - EncryptingPacker From b7a398efe2a5d48594f3432e345fc263cf6e358f Mon Sep 17 00:00:00 2001 From: EdOverflow Date: Thu, 22 Dec 2016 15:57:51 +0100 Subject: [PATCH 5/5] Fix SyntaxError --- tests/py/test_security.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/tests/py/test_security.py b/tests/py/test_security.py index 1a15e6e628..2d741bcd91 100644 --- a/tests/py/test_security.py +++ b/tests/py/test_security.py @@ -55,14 +55,15 @@ def test_ahtr_sets_x_xss_protection(self): def test_ahtr__csp(self): headers = self.client.GET('/about/').headers - assert headers['content-security-policy'] = ( 'default-src \'self\';' - 'script-src assets.gratipay.com;' - 'style-src assets.gratipay.com;' - 'img-src *;' - 'font-src cloud.typography.com;' - 'upgrade-insecure-requests;' - 'block-all-mixed-content;' - 'reflected-xss block;') + policy = ('default-src \'self\';' + 'script-src assets.gratipay.com;' + 'style-src assets.gratipay.com;' + 'img-src *;' + 'font-src cloud.typography.com;' + 'upgrade-insecure-requests;' + 'block-all-mixed-content;' + 'reflected-xss block;') + assert headers['content-security-policy'] == policy # ep - EncryptingPacker