11import re
22
3+ import bleach
34from django import template
45from django .utils .html import escape
56from django .utils .safestring import mark_safe
1112# same position — e.g. `a**b**c` stays a code span, the inner ** is not bolded.
1213_INLINE_RE = re .compile (r"`([^`]+)`|\*\*([^*]+?)\*\*" )
1314
15+ # The only tags inline_markdown is allowed to emit. bleach (already a project
16+ # dependency via wagtail-markdown) is the source of truth for this allowlist.
17+ _ALLOWED_TAGS = ["code" , "strong" ]
18+
1419
1520def _replace_span (match ):
1621 if match .group (1 ) is not None :
@@ -23,9 +28,12 @@ def inline_markdown(value):
2328 """Render inline-code (`...`) and bold (**...**) markdown spans as HTML.
2429
2530 Scoped to what `WHATS_NEW_SYSTEM_PROMPT` permits in description bullets:
26- code identifiers in single backticks and double-asterisk bold. Everything
27- else in the input is HTML-escaped.
31+ code identifiers in single backticks and double-asterisk bold. The input is
32+ escaped first so raw markup becomes inert text, the two permitted spans are
33+ converted, then `bleach.clean` enforces the allowlist on the result.
2834 """
2935 if not value :
3036 return ""
31- return mark_safe (_INLINE_RE .sub (_replace_span , escape (value )))
37+ html = _INLINE_RE .sub (_replace_span , escape (value ))
38+ cleaned = bleach .clean (html , tags = _ALLOWED_TAGS , attributes = {}, strip = True )
39+ return mark_safe (cleaned )
0 commit comments