diff --git a/gratipay/security/__init__.py b/gratipay/security/__init__.py index 1f41550385..b265df32ae 100644 --- a/gratipay/security/__init__.py +++ b/gratipay/security/__init__.py @@ -40,3 +40,16 @@ 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\';' + '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;') diff --git a/tests/py/test_security.py b/tests/py/test_security.py index eae24c24dd..2d741bcd91 100644 --- a/tests/py/test_security.py +++ b/tests/py/test_security.py @@ -53,6 +53,18 @@ 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 + 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