Commit 91cdbde6 authored by Vincent Pelletier's avatar Vincent Pelletier

HTTP: Strip nonce values from Content-Security-Policy headers

Thus stabilising the value of these headers.
parent e335e8fb
......@@ -17,6 +17,7 @@
# See COPYING file for full licensing terms.
# See https://www.nexedi.com/licensing for rationale and options.
import re
import requests
import sys
import traceback
......@@ -29,6 +30,8 @@ PREFERRED_TYPE = "text/html"
TIMEOUT = 2
ELAPSED_FAST = 0.2
ELAPSED_MODERATE = 0.5
SUB_CSP_NONCE_REPL = "'nonce-'"
SUB_CSP_NONCE = re.compile(r"'nonce-[^']*'").sub
def getUrlHostname(url):
......@@ -244,7 +247,6 @@ def checkHttpStatus(
"Content-Encoding",
"Content-Disposition",
# Security
"Content-Security-Policy",
"Referrer-Policy",
"Strict-Transport-Security",
"Feature-Policy",
......@@ -263,6 +265,15 @@ def checkHttpStatus(
if header_value is not None:
header_dict[header_key] = header_value
# Strip nonces from Content-Security-Policy
header_key = "Content-Security-Policy"
content_security_policy = response.headers.get(header_key, None)
if content_security_policy is not None:
header_dict[header_key] = SUB_CSP_NONCE(
repl=SUB_CSP_NONCE_REPL,
string=content_security_policy,
)
# Store key only, because of non stability
# 'Etag', 'Last-Modified', 'Set-Cookie', 'Date', 'Age'
key_only_header_list = [
......
......@@ -1001,6 +1001,36 @@ class SurykatkaHttpTestCase(unittest.TestCase):
result_dict[header] = header + " bar"
return result_dict
@httpretty.activate
def test_checkContentSecurityPolicyNonceStripper(self):
header_key = "Content-Security-Policy"
httpretty.register_uri(
httpretty.GET,
"http://127.0.0.1/foo?bar=1",
status=418,
adding_headers={
header_key: (
"script-src 'self' 'nonce-dHkctJcn0BOAQxGH1YNXbg==' 'strict-dynamic';"
"style-src 'self' 'nonce-dHkctJcn0BOAQxGH1YNXbg==';"
"object-src 'none';"
),
},
)
checkHttpStatus(
self.db,
logStatus(self.db, "foo"),
"http://example.org/foo?bar=1",
"127.0.0.1",
1,
"http://example.org/contact",
)
assert self.db.HttpCodeChange.select().count() == 1
assert self.db.HttpCodeChange.get().http_header_dict[header_key] == (
"script-src 'self' 'nonce-' 'strict-dynamic';"
"style-src 'self' 'nonce-';"
"object-src 'none';"
)
@httpretty.activate
def test_checkHttpStatus_whitelistHttpHeader(self):
ip = "127.0.0.1"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment