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"]*>", + 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 "