diff --git a/datasette/tracer.py b/datasette/tracer.py index 772f0405..62c3c90c 100644 --- a/datasette/tracer.py +++ b/datasette/tracer.py @@ -1,5 +1,6 @@ import asyncio from contextlib import contextmanager +from markupsafe import escape import time import json import traceback @@ -123,7 +124,7 @@ class AsgiTracer: except IndexError: content_type = "" if "text/html" in content_type and b"" in accumulated_body: - extra = json.dumps(trace_info, indent=2) + extra = escape(json.dumps(trace_info, indent=2)) extra_html = f"
{extra}
".encode("utf8") accumulated_body = accumulated_body.replace(b"", extra_html) elif "json" in content_type and accumulated_body.startswith(b"{"): diff --git a/tests/test_html.py b/tests/test_html.py index f1d4bd70..8714d254 100644 --- a/tests/test_html.py +++ b/tests/test_html.py @@ -1699,3 +1699,9 @@ def test_unavailable_table_does_not_break_sort_relationships(): ) as client: response = client.get("/?_sort=relationships") assert response.status == 200 + + +def test_trace_correctly_escaped(app_client): + response = app_client.get("/fixtures?sql=select+'

Hello'&_trace=1") + assert "select '

Hello" not in response.text + assert "select '<h1>Hello" in response.text