Optimized more CSP policies and recaptcha

This commit is contained in:
Kevin Veen-Birkenbach 2025-05-15 19:36:46 +02:00
parent 2302cbfeb4
commit 9c65c320f9
No known key found for this signature in database
GPG Key ID: 44D8F11FD62F878E
8 changed files with 48 additions and 19 deletions

View File

@ -20,7 +20,7 @@ install: build
@echo "⚙️ Install complete." @echo "⚙️ Install complete."
test: test:
@echo "\n🧪 Running Unit Tests..." @echo "🧪 Running Unit Tests..."
python -m unittest discover -s tests/unit python -m unittest discover -s tests/unit
@echo "\n🔬 Running Integration Tests..." @echo "🔬 Running Integration Tests..."
python -m unittest discover -s tests/integration python -m unittest discover -s tests/integration

View File

@ -113,6 +113,13 @@ class FilterModule(object):
if matomo_domain: if matomo_domain:
tokens.append(f"{web_protocol}://{matomo_domain}") tokens.append(f"{web_protocol}://{matomo_domain}")
# ReCaptcha integration: allow loading scripts from Google if feature enabled
if (
self.is_feature_enabled(applications, 'recaptcha', application_id)
and directive == 'script-src'
):
tokens.append('https://www.google.com')
# whitelist # whitelist
tokens += self.get_csp_whitelist(applications, application_id, directive) tokens += self.get_csp_whitelist(applications, application_id, directive)

View File

@ -4,8 +4,6 @@ users:
username: "{{users.administrator.username}}" # Administrator Username for Keycloak username: "{{users.administrator.username}}" # Administrator Username for Keycloak
import_realm: True # If True realm will be imported. If false skip. import_realm: True # If True realm will be imported. If false skip.
credentials: credentials:
# database_password: # Needs to be defined in inventory file
# administrator_password: # Needs to be defined in inventory file
features: features:
matomo: true matomo: true
css: true css: true
@ -13,3 +11,7 @@ features:
ldap: true ldap: true
central_database: true central_database: true
recaptcha: true recaptcha: true
csp:
flags:
script-src:
unsafe-inline: true

View File

@ -6,7 +6,7 @@ users:
version: "latest" version: "latest"
features: features:
matomo: true matomo: true
css: true css: false
portfolio_iframe: false portfolio_iframe: false
central_database: true central_database: true
csp: csp:
@ -20,4 +20,5 @@ csp:
font-src: font-src:
- "data:" - "data:"
- "blob:" - "blob:"
script-src:
- "https://cdn.jsdelivr.net" - "https://cdn.jsdelivr.net"

View File

@ -28,10 +28,9 @@ csp:
- "blob:" - "blob:"
font-src: font-src:
- "data:" - "data:"
- "https://fonts.bunny.net"
script-src: script-src:
- "https://cdn.gtranslate.net" - "https://cdn.gtranslate.net"
- "{{ domains.wordpress[0] }}" - "{{ domains.wordpress[0] }}"
frame-src:
- "{{ domains.peertube }}"
style-src: style-src:
- "https://fonts.bunny.net" - "https://fonts.bunny.net"

View File

@ -137,5 +137,25 @@ class TestCspFilters(unittest.TestCase):
style_hash = self.filter.get_csp_hash("body { background: #fff; }") style_hash = self.filter.get_csp_hash("body { background: #fff; }")
self.assertNotIn(style_hash, header) self.assertNotIn(style_hash, header)
def test_build_csp_header_recaptcha_toggle(self):
"""
When the 'recaptcha' feature is enabled, 'https://www.google.com'
must be included in script-src; when disabled, it must not be.
"""
# enabled case
self.apps['app1']['features']['recaptcha'] = True
header_enabled = self.filter.build_csp_header(
self.apps, 'app1', self.domains, web_protocol='https'
)
self.assertIn("https://www.google.com", header_enabled)
# disabled case
self.apps['app1']['features']['recaptcha'] = False
header_disabled = self.filter.build_csp_header(
self.apps, 'app1', self.domains, web_protocol='https'
)
self.assertNotIn("https://www.google.com", header_disabled)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()