mirror of
https://github.com/nesquena/hermes-webui.git
synced 2026-05-19 13:47:04 +00:00
fix(security): drop unsafe-eval + add jsdelivr to CSP, sanitize plugin error
Opus stage-339 review SHOULD-FIX items: 1. server.py: drop 'unsafe-eval' from CSP report-only policy. Verified by grepping all production JS — zero matches for eval(), new Function(), or string-form setTimeout/setInterval. Keeping it was a gratuitous privilege. 2. server.py: add https://cdn.jsdelivr.net to script-src + style-src. index.html loads Prism/xterm/katex from this CDN with SRI hashes — without the allowance every page load fires known-good CSP violations that drown out real signal once a collector is wired. 3. api/commands.py: sanitize plugin command error. Previously returned f'Plugin command error: {exc}' which would leak paths/env from FileNotFoundError('/etc/something/secret.key') etc. Now returns only the exception type name; full traceback goes to server log. Test asserts updated to match the new policy shape. Co-authored-by: Opus advisor <opus-advisor@hermes.local>
This commit is contained in:
+5
-1
@@ -117,4 +117,8 @@ def execute_plugin_command(command: str) -> str:
|
||||
result = resolve_plugin_command_result(handler(cmd_arg))
|
||||
return str(result or "(no output)")
|
||||
except Exception as exc:
|
||||
return f"Plugin command error: {exc}"
|
||||
# Don't leak raw exception str (paths, env, internal state) to the
|
||||
# user-facing chat. Type name is enough for the user to know what
|
||||
# class of failure occurred; full traceback lives in the server log.
|
||||
logger.warning("Plugin command %r failed", cmd_base, exc_info=exc)
|
||||
return f"Plugin command error: {type(exc).__name__}"
|
||||
|
||||
@@ -205,8 +205,8 @@ class Handler(BaseHTTPRequestHandler):
|
||||
"base-uri 'self'; "
|
||||
"object-src 'none'; "
|
||||
"frame-ancestors 'self'; "
|
||||
"script-src 'self' 'unsafe-inline' 'unsafe-eval'; "
|
||||
"style-src 'self' 'unsafe-inline'; "
|
||||
"script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net; "
|
||||
"style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net; "
|
||||
"img-src 'self' data: blob:; "
|
||||
"font-src 'self' data:; "
|
||||
"media-src 'self' data: blob:; "
|
||||
|
||||
@@ -26,7 +26,10 @@ def test_handler_adds_content_security_policy_report_only(monkeypatch):
|
||||
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 "script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net" in policy
|
||||
assert "style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net" in policy
|
||||
# unsafe-eval was dropped after Opus stage-339 verification — no production
|
||||
# JS uses eval(), new Function(), or string-form setTimeout/setInterval.
|
||||
assert "'unsafe-eval'" not in policy
|
||||
assert "img-src 'self' data: blob:" in policy
|
||||
assert "connect-src 'self'" in policy
|
||||
|
||||
Reference in New Issue
Block a user