python 39 lines · 5 steps

Sanitizing user HTML with bleach

Whitelist safe tags and attributes, strip everything else, then harden auto-generated links against tabnabbing.

Explained by highlit
1import bleach
2 
3ALLOWED_TAGS = [
4 "a", "b", "strong", "i", "em", "u",
5 "p", "br", "ul", "ol", "li", "blockquote",
6 "code", "pre", "h1", "h2", "h3",
7]
8 
9ALLOWED_ATTRIBUTES = {
10 "a": ["href", "title", "rel"],
11}
12 
13ALLOWED_PROTOCOLS = ["http", "https", "mailto"]
14 
15 
16def sanitize_user_html(raw: str) -> str:
17 cleaned = bleach.clean(
18 raw,
19 tags=ALLOWED_TAGS,
20 attributes=ALLOWED_ATTRIBUTES,
21 protocols=ALLOWED_PROTOCOLS,
22 strip=True,
23 strip_comments=True,
24 )
25 
26 linker = bleach.linkifier.Linker(
27 callbacks=[_force_noopener],
28 skip_tags=["pre", "code"],
29 )
30 return linker.linkify(cleaned)
31 
32 
33def _force_noopener(attrs, new=False):
34 href_key = (None, "href")
35 if href_key not in attrs:
36 return attrs
37 attrs[(None, "rel")] = "nofollow noopener noreferrer"
38 attrs[(None, "target")] = "_blank"
39 return attrs
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1A whitelist of allowed tags and attributes is safer than trying to blacklist dangerous markup.
  2. 2Restricting URL protocols blocks javascript: and data: vectors that survive tag filtering.
  3. 3Auto-generated links should carry rel=noopener noreferrer to prevent reverse-tabnabbing attacks.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Sanitizing user HTML with bleach — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code