mirror of
https://github.com/nesquena/hermes-webui.git
synced 2026-05-25 11:10:18 +00:00
Merge PR #2084 into stage-339
fix: add report-only CSP header by @ai-ag2026
This commit is contained in:
@@ -200,6 +200,27 @@ class Handler(BaseHTTPRequestHandler):
|
||||
pass
|
||||
_ver_suffix = WEBUI_VERSION.removeprefix('v')
|
||||
server_version = ('HermesWebUI/' + _ver_suffix) if _ver_suffix != 'unknown' else 'HermesWebUI'
|
||||
_CSP_REPORT_ONLY = (
|
||||
"default-src 'self'; "
|
||||
"base-uri 'self'; "
|
||||
"object-src 'none'; "
|
||||
"frame-ancestors 'self'; "
|
||||
"script-src 'self' 'unsafe-inline' 'unsafe-eval'; "
|
||||
"style-src 'self' 'unsafe-inline'; "
|
||||
"img-src 'self' data: blob:; "
|
||||
"font-src 'self' data:; "
|
||||
"media-src 'self' data: blob:; "
|
||||
"connect-src 'self' http://127.0.0.1:* http://localhost:* ws://127.0.0.1:* ws://localhost:*"
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def csp_report_only_policy(cls) -> str:
|
||||
return cls._CSP_REPORT_ONLY
|
||||
|
||||
def end_headers(self) -> None:
|
||||
self.send_header("Content-Security-Policy-Report-Only", self.csp_report_only_policy())
|
||||
super().end_headers()
|
||||
|
||||
def log_message(self, fmt, *args): pass # suppress default Apache-style log
|
||||
|
||||
def log_request(self, code: str='-', size: str='-') -> None:
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
"""Regression tests for #1909 CSP report-only security header."""
|
||||
|
||||
from http.server import BaseHTTPRequestHandler
|
||||
|
||||
from server import Handler
|
||||
|
||||
|
||||
def test_handler_adds_content_security_policy_report_only(monkeypatch):
|
||||
sent_headers = []
|
||||
handler = Handler.__new__(Handler)
|
||||
handler.send_header = lambda key, value: sent_headers.append((key, value))
|
||||
monkeypatch.setattr(BaseHTTPRequestHandler, "end_headers", lambda self: None)
|
||||
|
||||
Handler.end_headers(handler)
|
||||
|
||||
headers = dict(sent_headers)
|
||||
assert "Content-Security-Policy-Report-Only" in headers
|
||||
assert "Content-Security-Policy" not in headers
|
||||
policy = headers["Content-Security-Policy-Report-Only"]
|
||||
assert "default-src 'self'" in policy
|
||||
assert "object-src 'none'" in policy
|
||||
assert "frame-ancestors 'self'" in policy
|
||||
assert "base-uri 'self'" in policy
|
||||
|
||||
|
||||
def test_csp_report_only_keeps_legacy_inline_allowances_for_current_ui():
|
||||
policy = Handler.csp_report_only_policy()
|
||||
|
||||
assert "script-src 'self' 'unsafe-inline' 'unsafe-eval'" in policy
|
||||
assert "style-src 'self' 'unsafe-inline'" in policy
|
||||
assert "img-src 'self' data: blob:" in policy
|
||||
assert "connect-src 'self'" in policy
|
||||
Reference in New Issue
Block a user