ToolsGrid
File Privacy
Web Security & Compiler Architecture

Markdown AST Parsing, CommonMark Rules & Client-Side XSS Sanitization

Why regex-based Markdown parsers are dangerous, how modern Abstract Syntax Tree tokenizers interpret GitHub Flavored Markdown (GFM), and how in-browser DOM sanitization neutralizes Cross-Site Scripting (XSS).

6 min read • October 2026 • Compiler Engineering

When John Gruber created Markdown in 2004, the objective was elegant simplicity: to make writing web documents as frictionless as composing plain text emails. However, Gruber's original Perl script relied heavily on regular expressions. As Markdown spread across GitHub, Reddit, Slack, and Discord, developers discovered that regex parsing fails when confronted with deeply nested lists, unclosed code fences, and ambiguous emphasis markers.

More critically, Markdown by specification allows raw inline HTML. If you render user-supplied Markdown directly on a webpage without sanitization, you introduce Cross-Site Scripting (XSS) vulnerabilities. This article explains how modern parsers actually work, which attack payloads matter, and where sanitization has to happen.

Looking for a complete step-by-step tutorial on translating Markdown to semantic HTML?
Read Step-by-Step Markdown Guide

01. From Raw String to AST: The Modern Parsing Pipeline

Modern Markdown engines such as markdown-it, marked, micromark and remark follow the CommonMark specification, which defines parsing as a deterministic, multi-stage process instead of a series of find-and-replace passes:

  1. Block structure: the engine reads the document line by line and decides which block each line belongs to: headings, lists, blockquotes, fenced code, tables (a GFM extension) and paragraphs. Containers can nest, so a list item may hold a blockquote that holds a code block.
  2. Inline parsing: inside each paragraph or heading the engine tokenizes emphasis, code spans, links, images and autolinks. Emphasis is resolved with a delimiter-run algorithm that matches openers and closers, which is why **bold *italic** text* has one well-defined result instead of depending on regex luck.
  3. AST generation: the result is a tree of typed nodes. A renderer walks this tree and emits HTML, PDF or plain text.
// Source Markdown: > **Important Note**: Check [documentation](https://toolsgrid.online/) // Parsed AST representation:
BlockquoteNode {
  ParagraphNode {
    StrongNode { text: "Important Note" },
    TextNode   { text: ": Check " },
    LinkNode   { href: "https://toolsgrid.online/", text: "documentation" }
  }
}

The tree is the important part. Because every piece of content is a typed node, a program can inspect, rewrite or reject nodes (for example, drop every LinkNode whose href is not http or https) before any HTML string exists. Regex pipelines never get that chance, since they go straight from text to text.

02. The Dangerous XSS Attack Vectors in Markdown

CommonMark deliberately passes raw HTML blocks and inline HTML through to the output. Parsers differ in their defaults: markdown-it ships with html: false, while marked renders raw HTML as written and its own documentation warns that it does not sanitize output. Attackers exploit exactly that gap:

Attack TechniqueMalicious Markdown VectorExploitation Risk
Inline Script Tags<script>fetch('/steal?c='+document.cookie)</script>Session hijacking & authentication theft
Event Handler Injection<img src="invalid" onerror="alert(document.domain)">Script execution as soon as the image fails to load
Pseudo-Protocol Links[Click for Free PDF](javascript:stealData())Script execution when the victim clicks the link
Embedded Frames<iframe src="https://evil.example"></iframe>Phishing overlays and clickjacking inside your page

Notice that none of these payloads need a Markdown bug. They are valid Markdown that the specification asks the parser to preserve. The security boundary therefore cannot live inside the Markdown parser alone.

03. Why Regex Filters Fail and Allowlist Sanitizers Work

The instinctive fix is a regex that deletes <script>. It fails because browsers are forgiving HTML parsers: <scr<script>ipt>, mixed-case tags, unquoted attributes, HTML entities inside javascript: URLs and malformed nesting all slip through a denylist. Sanitization has to run on a real parsed DOM, with an allowlist of tags and attributes that are known to be safe.

DOMPurify is the widely used implementation of this idea. It parses the HTML into an inert document, walks every node, keeps only allowlisted elements and attributes, removes event-handler attributes, and rejects dangerous URL schemes. Two rules matter in practice:

  • Sanitize last. Run the sanitizer on the final HTML string that will be inserted into the page. If you modify the HTML after sanitizing it, you can re-introduce the problem.
  • Sanitize where it is rendered. Pre-sanitizing on the server does not help a client that later concatenates strings, and a client-side check does not protect other consumers of the same HTML.

Defense in depth adds a Content-Security-Policy that forbids inline scripts, so that a sanitizer bug or a missed code path is not an automatic compromise.

04. How ToolsGrid Handles It

The Markdown to HTML Converter parses your text with marked in your own browser. Nothing is uploaded: your design documents, roadmaps and unreleased posts stay in local JavaScript memory.

The Visual Preview pane is passed through DOMPurify before it is mounted, so a pasted <img onerror=...> or javascript: link will not execute in your session. The Raw HTML pane and the Copy HTML button deliberately return the converter's exact output, because stripping tags from the code you copy would silently change your document.

Before you publish: if the Markdown comes from users you do not control, run the copied HTML through a sanitizer on your own site as well. The preview being safe does not make the copied markup safe.

05. A Practical Checklist

  • Treat every Markdown source you do not author yourself as untrusted input, including comments, tickets and imported documents.
  • Prefer parsers that disable raw HTML by default, or sanitize with an allowlist when you need to keep it.
  • Allow only http, https and mailto link schemes, and add rel="noopener noreferrer" to external links.
  • Sanitize the final HTML string, then insert it. Do not edit it afterwards.
  • Add a Content-Security-Policy that blocks inline scripts as a second layer.
Markdown to HTML, safely

Convert Markdown with a Sanitized Live Preview

Paste GitHub Flavored Markdown and see the rendered result instantly. The preview is sanitized with DOMPurify and everything runs locally in your browser.

Frequently Asked Markdown Security Questions

Why can raw Markdown allow Cross-Site Scripting (XSS)?

The original Markdown specification explicitly allows inline HTML. If untrusted user input contains raw <script> tags, malicious <iframe> elements, or inline event handlers like <img src=x onerror=alert(1)>, converting it directly into innerHTML can execute arbitrary attacker code.

What is an Abstract Syntax Tree (AST) in Markdown processing?

An AST is a hierarchical tree representation of source markup. Rather than using brittle regex string replacements, an AST tokenizer maps text into discrete typed nodes (Heading, List, CodeBlock, Paragraph), allowing deterministic transformation into HTML or PDF.

How does DOMPurify sanitize rendered HTML?

DOMPurify parses generated HTML through an isolated browser DOM tree, stripping dangerous tags (script, object, embed), sanitizing URL protocols (preventing javascript: pseudo-protocols), and deleting unexpected inline event handlers before outputting safe markup.

Does the ToolsGrid Markdown converter sanitize its output?

The Visual Preview is passed through DOMPurify before it is inserted into the page. The Raw HTML pane and the Copy HTML button return the converter's unmodified output, so you should sanitize that HTML yourself before publishing untrusted Markdown on your own site.

TG
Written by The ToolsGrid Developer Team

ToolsGrid engineers build private, client-side utilities for developers. We write about parsing, security and web standards from the point of view of tools that run entirely in your browser.

Previous: Debugging Malformed JSON

Explore Free Career & Document Utilities

Discover our full suite of fast, private, browser-based web tools

View All Tools