diff --git a/src/claude_code_transcripts/__init__.py b/src/claude_code_transcripts/__init__.py index e4854a3b..b62c31ff 100644 --- a/src/claude_code_transcripts/__init__.py +++ b/src/claude_code_transcripts/__init__.py @@ -698,10 +698,40 @@ def format_json(obj): return f"
{html.escape(str(obj))}"
+# Tags that can execute code or navigate the page if they survive as live HTML.
+# Python-Markdown passes raw HTML through verbatim, so any of these present in a
+# message (outside a code fence, where the angle brackets would be escaped)
+# become live elements. A real example: pasted captive-portal debug logs holding
+#
+# hijack the transcript on load and it never renders. Markdown never emits these
+# tags itself, so escaping them back to visible text leaves normal content alone.
+_ACTIVE_TAG_RE = re.compile(
+ r"?\s*(?:script|iframe|object|embed|applet|meta|link|base|frame|frameset|form)\b[^>]*>",
+ re.I,
+)
+# Inline event handlers (onerror=, onload=, …) and javascript: URIs execute
+# without a "
+ )
+ assert "\n```"
+ )
+ assert "bold" in result
+ assert "code" in result
+ assert 'href="http://ok"' in result
+ # Inside a fence markdown already escapes it; must stay visible text.
+ assert "