Skip to content

Commit

Permalink
fixup! Fix: Content Security Policy (CSP) Not Implemented (DataBiosph…
Browse files Browse the repository at this point in the history
  • Loading branch information
dsotirho-ucsc committed Nov 14, 2024
1 parent 89c839e commit 0d8d886
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 14 deletions.
22 changes: 12 additions & 10 deletions src/azul/chalice.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@
from furl import (
furl,
)
from more_itertools import (
one,
)

from azul import (
config,
Expand Down Expand Up @@ -242,14 +239,20 @@ def content_security_policy(cls, nonce: str | None = None) -> str:
])

@classmethod
def validate_csp(cls, csp: str, has_nonce: bool) -> Optional[str]:
def validate_csp(cls, csp: str, has_nonce: bool) -> str:
"""
Raises an exception if the CSP is invalid. Returns a nonce token if the
CSP contained one, else None.
Raises an exception if the CSP is invalid, otherwise returns the
validated CSP.
>>> cls = AzulChaliceApp
>>> cls.validate_csp("default-src 'self';img-src 'self' data:;"
... "script-src 'self';"
... "style-src 'self';"
... "frame-ancestors 'none'", has_nonce=False)
"default-src 'self';img-src 'self' data:;script-src 'self';style-src 'self';frame-ancestors 'none'"
Fails if nonce violates the RFC
>>> cls = AzulChaliceApp
>>> cls.validate_csp("default-src 'self';img-src 'self' data:;"
... "script-src 'self' 'nonce-1234567890123456789012345678901234567890***';"
... "style-src 'self' 'nonce-1234567890123456789012345678901234567890***';"
Expand Down Expand Up @@ -317,13 +320,12 @@ def validate_csp(cls, csp: str, has_nonce: bool) -> Optional[str]:
nonces[name] = match.group(1)
if has_nonce:
assert ['script-src', 'style-src'] == sorted(nonces.keys()), nonces.keys()
nonce = one(set(nonces.values()))
assert len(set(nonces.values())) == 1, sorted(set(nonces.values()))
else:
assert nonces == {}, nonces
nonce = None
assert expected_directives == sorted(directives), sorted(directives)
assert expected_expressions == sorted(set(expressions)), sorted(set(expressions))
return nonce
return csp

@classmethod
def security_headers(cls) -> dict[str, str]:
Expand Down
7 changes: 3 additions & 4 deletions test/integration_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2006,10 +2006,9 @@ def test_response_security_headers(self):
response = requests.get(str(endpoint / path))
response.raise_for_status()
expected = AzulChaliceApp.security_headers() | expected_headers
nonce = AzulChaliceApp.validate_csp(response.headers['Content-Security-Policy'],
has_nonce=path in ['/', '/oauth2_redirect'])
expected_csp = AzulChaliceApp.content_security_policy(nonce)
expected['Content-Security-Policy'] = expected_csp
csp = AzulChaliceApp.validate_csp(response.headers['Content-Security-Policy'],
has_nonce=path in ['/', '/oauth2_redirect'])
expected['Content-Security-Policy'] = csp
self.assertIsSubset(expected.items(), response.headers.items())

def test_default_4xx_response_headers(self):
Expand Down

0 comments on commit 0d8d886

Please sign in to comment.