I think you should use a separate HTML sanitizer, like DOMpurify, and not rely on your commonmark implementation to produce safe markup. The resulting pipeline will be “commonmark → dompurify → renderer”. This is a hill I will die on: commonmark parsers that let you disable inline HTML are offering an antifeature, including the reference cmark implementation.
There are two reasons why it’s a bad idea to rely on your commonmark implementation as a security boundary:
-
There’s more to safely embedding UGC than just disabling inline and block HTML tags. You also need to filter out
javascript:anddata:URIs, you need to make sure the resulting HTML is properly nested, and, if you generateidfrom user input, need to ensure it doesn’t collide with parts of the host page..markdown-it used to be vulnerable to the
data:URL thing and pulldown-cmark used to produce invalid HTML in some cases, so these problems aren’t just theoretical. -
There are expressiveness holes in commonmark that can only be filled by using HTML. You can try to fix them, but there’s only so much punctuation on the keyboard. You either wind up reinventing HTML but worse, or you wind up with markup that can’t actually express everything.