Sanitize untrusted HTML¶
Clean untrusted HTML against an allowlist with turbohtml.clean.sanitize(), the bleach.clean successor, keeping
only a safe subset of tags, attributes, and URL schemes.
Sanitize untrusted HTML¶
To clean user-submitted HTML the way bleach.clean did, use turbohtml.clean.sanitize(). A
Policy says what to keep (here the relaxed preset for typical user content), and a
non-overridable baseline drops scripting and javascript: URLs no matter what the policy allows:
from turbohtml.clean import sanitize, Policy
print(sanitize("<p>Hi <a href='javascript:alert(1)'>link</a></p><script>evil()</script>", Policy.relaxed()))
<p>Hi <a>link</a></p><script>evil()</script>
Trust the first pass, do not reparse¶
Sanitizing is a single parse pass, like DOMPurify. Its output is safe to insert into a DOM as it stands. Do not parse it again with a different engine or in a different context and then trust that second tree.
HTML parsing is not a fixpoint: serialize a tree and reparse it, and you can get a different tree. In foreign content a
</p> or </br> end tag builds an HTML element inside the SVG/MathML root, while the matching start tag on a
later parse breaks out of it; a raw carriage return in text also becomes a newline on reparse. sanitize resolves
all of that in its one pass, so the string it returns is inert. Reparsing and reserializing that string can yield a
different string that is still inert. The guarantee is inertness, not byte-stable output across a round trip.