From 1f57ed2a53f0ab4eec515c8a6abf44dc1e52fdaa Mon Sep 17 00:00:00 2001 From: Adolanium <94890352+Adolanium@users.noreply.github.com> Date: Thu, 9 Jul 2026 10:28:12 +0300 Subject: [PATCH] fix(export): escape tool-call name in HTML session export The HTML session export interpolated the tool-call name into the page without escaping, while every sibling field went through _escape_html. A tool-call name is attacker-influenced, so a prompt-injected model can emit a name containing HTML that executes when the export is opened in a browser. Escape the tool-call name like the other fields. --- hermes_cli/session_export_html.py | 2 +- tests/hermes_cli/test_session_export_html.py | 60 ++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 tests/hermes_cli/test_session_export_html.py diff --git a/hermes_cli/session_export_html.py b/hermes_cli/session_export_html.py index 6b3821ed03e..2489cf653a7 100644 --- a/hermes_cli/session_export_html.py +++ b/hermes_cli/session_export_html.py @@ -706,7 +706,7 @@ def _generate_messages_html(messages: List[Dict[str, Any]]) -> str:
{_escape_html(args)}
diff --git a/tests/hermes_cli/test_session_export_html.py b/tests/hermes_cli/test_session_export_html.py
new file mode 100644
index 00000000000..cadfb6e19a1
--- /dev/null
+++ b/tests/hermes_cli/test_session_export_html.py
@@ -0,0 +1,60 @@
+"""Tests for the HTML session export renderer."""
+
+from hermes_cli.session_export_html import (
+ _generate_messages_html,
+ generate_multi_session_html_export,
+)
+
+
+def test_tool_call_name_is_escaped():
+ """A tool-call name is attacker-influenced (a prompt-injected model can emit
+ an arbitrary name), so it must be HTML-escaped like every sibling field."""
+ payload = '