[#8470] added new setting csp.report_enforce_mode and code update also updated tests
diff --git a/Allura/allura/lib/app_globals.py b/Allura/allura/lib/app_globals.py
index d657423..5895459 100644
--- a/Allura/allura/lib/app_globals.py
+++ b/Allura/allura/lib/app_globals.py
@@ -678,6 +678,12 @@
if config.get('csp.report_uri_enforce'):
return config['csp.report_uri_enforce']
return None
+ @property
+ def csp_report_enforce(self):
+ if config.get('csp.report_enforce_mode'):
+ return True
+ return False
+
class Icon:
def __init__(self, css, title=None):
diff --git a/Allura/allura/lib/custom_middleware.py b/Allura/allura/lib/custom_middleware.py
index 4515532..7665f64 100644
--- a/Allura/allura/lib/custom_middleware.py
+++ b/Allura/allura/lib/custom_middleware.py
@@ -468,24 +468,39 @@
def __call__(self, environ, start_response):
req = Request(environ)
resp = req.get_response(self.app)
- report_uri = ''
- report_suffix = ''
- report_uri_enforce = ''
- if g.csp_report_mode and g.csp_report_uri:
- report_suffix = '-Report-Only'
- report_uri = f'; report-uri {g.csp_report_uri}; report-to {g.csp_report_uri}'
- rules = resp.headers.getall(f'Content-Security-Policy{report_suffix}')
+ rules = resp.headers.getall('Content-Security-Policy')
+ report_rules = resp.headers.getall('Content-Security-Policy-Report-Only')
+
if rules:
- resp.headers.pop(f'Content-Security-Policy{report_suffix}')
+ resp.headers.pop('Content-Security-Policy')
+ if report_rules:
+ resp.headers.pop('Content-Security-Policy-Report-Only')
+
+ if g.csp_report_mode and g.csp_report_uri:
+ report_rules.append(f'report-uri {g.csp_report_uri}; report-to {g.csp_report_uri}')
+
if self.config['base_url'].startswith('https'):
rules.append('upgrade-insecure-requests')
- if g.csp_report_uri_enforce:
- report_uri_enforce = f'; report-uri {g.csp_report_uri_enforce}; report-to {g.csp_report_uri_enforce:}'
+
+ if g.csp_report_enforce and g.csp_report_uri_enforce:
+ rules.append(f'report-uri {g.csp_report_uri_enforce}; report-to {g.csp_report_uri_enforce:}')
+
if self.config.get('csp.frame_sources'):
- rules.append(f"frame-src {self.config['csp.frame_sources']}{report_uri}{report_uri_enforce}")
+ if g.csp_report_mode:
+ report_rules.append(f"frame-src {self.config['csp.frame_sources']}")
+ else:
+ rules.append(f"frame-src {self.config['csp.frame_sources']}")
+
if self.config.get('csp.form_action_urls'):
- rules.append(f"form-action {self.config['csp.form_action_urls']}{report_uri}{report_uri_enforce}")
+ if g.csp_report_mode:
+ report_rules.append(f"form-action {self.config['csp.form_action_urls']}")
+ else:
+ rules.append(f"form-action {self.config['csp.form_action_urls']}")
+
rules.append("object-src 'none'")
rules.append("frame-ancestors 'self'")
- resp.headers.add(f'Content-Security-Policy{report_suffix}', '; '.join(rules))
+ if rules:
+ resp.headers.add('Content-Security-Policy', '; '.join(rules))
+ if report_rules:
+ resp.headers.add('Content-Security-Policy-Report-Only', '; '.join(report_rules))
return resp(environ, start_response)
diff --git a/Allura/allura/tests/functional/test_root.py b/Allura/allura/tests/functional/test_root.py
index cb61065..6964fa0 100644
--- a/Allura/allura/tests/functional/test_root.py
+++ b/Allura/allura/tests/functional/test_root.py
@@ -190,26 +190,27 @@
def test_headers(self):
resp = self.app.get('/p')
- assert resp.headers.getall('Content-Security-Policy') == ["frame-src 'self' www.youtube-nocookie.com",
+ assert resp.headers.getall('Content-Security-Policy')[0] == '; '.join(["frame-src 'self' www.youtube-nocookie.com",
"form-action 'self'",
"object-src 'none'",
- "frame-ancestors 'self'"]
+ "frame-ancestors 'self'"])
def test_headers_config(self):
resp = self.app.get('/p')
- assert "frame-src 'self' www.youtube-nocookie.com" in resp.headers.getall('Content-Security-Policy')
+ assert "frame-src 'self' www.youtube-nocookie.com;" in resp.headers.getall('Content-Security-Policy')[0]
@mock.patch.dict(tg.config, {'csp.report_mode': True, 'csp.report_uri': 'https://example.com/r/d/csp/reportOnly'})
def test_headers_report(self):
resp = self.app.get('/p/wiki/Home/')
- assert resp.headers.getall('Content-Security-Policy-Report-Only') == [
- "frame-src 'self' www.youtube-nocookie.com; report-uri https://example.com/r/d/csp/reportOnly; report-to https://example.com/r/d/csp/reportOnly",
- "form-action 'self'; report-uri https://example.com/r/d/csp/reportOnly; report-to https://example.com/r/d/csp/reportOnly"]
+ assert resp.headers.getall('Content-Security-Policy-Report-Only')[0] == '; '.join(["report-uri https://example.com/r/d/csp/reportOnly",
+ "report-to https://example.com/r/d/csp/reportOnly",
+ "frame-src 'self' www.youtube-nocookie.com",
+ "form-action 'self'"])
- @mock.patch.dict(tg.config, {'csp.report_uri_enforce': 'https://example.com/r/d/csp/enforce'})
+ @mock.patch.dict(tg.config, {'csp.report_uri_enforce': 'https://example.com/r/d/csp/enforce', 'csp.report_enforce_mode': True})
def test_headers_report_enforce(self):
resp = self.app.get('/p/wiki/Home/')
- assert "frame-src 'self' www.youtube-nocookie.com; report-uri https://example.com/r/d/csp/enforce; report-to https://example.com/r/d/csp/enforce" in resp.headers.getall('Content-Security-Policy')
+ assert "report-uri https://example.com/r/d/csp/enforce; report-to https://example.com/r/d/csp/enforce; frame-src 'self' www.youtube-nocookie.com;" in resp.headers.getall('Content-Security-Policy')[0]
class TestRootWithSSLPattern(TestController):
diff --git a/Allura/development.ini b/Allura/development.ini
index 03207ed..3ded52b 100644
--- a/Allura/development.ini
+++ b/Allura/development.ini
@@ -661,6 +661,7 @@
; CSP Headers
; enable report mode
; csp.report_mode = false
+; csp.report_enforce_mode = false
; csp.report_uri = https://example.com/r/d/csp/reportOnly
; csp.report_uri_enforce = https://example.com/r/d/csp/enforce