Markdown in responses is rendered
Why it matters
AI models produce markdown-formatted output by default: bold, italics, bulleted lists, headers, and inline code are the native vocabulary of modern LLM responses. Rendering that output as plain text means users see raw **asterisks** and ## hashes cluttering every answer, destroying readability and forcing users to mentally parse formatting tokens. This also degrades accessibility by collapsing semantic structure into an undifferentiated wall of text, failing the intent of WCAG 2.2 SC 1.3.1 (Info and Relationships).
Severity rationale
High because unreadable output is functionally broken even when the model response is technically correct.
Remediation
Install a markdown renderer and pipe AI message content through it in your message component at src/components/chat/MessageBubble.tsx. Pair it with Tailwind's typography plugin for clean default styling, and never render raw HTML from AI output without sanitization.
import ReactMarkdown from 'react-markdown';
<div className="prose dark:prose-invert">
<ReactMarkdown>{message.content}</ReactMarkdown>
</div>
Detection
-
ID:
markdown-rendering -
Severity:
high -
What to look for: Find where AI message content is displayed in the UI. Count all message rendering locations and for each classify whether content is rendered as plain text (wrapping message content in a plain paragraph) or passed through a markdown renderer. Look for
react-markdown,marked,remark,micromark, or custom markdown parsers inpackage.json. Check whether markdown syntax would render as formatted HTML or appear as raw asterisks and hashes. -
Pass criteria: AI response content is rendered through a markdown parser in at least 1 rendering location. Bold, italic, headers, unordered and ordered lists, and inline code appear as formatted HTML, not raw markdown syntax.
-
Fail criteria: Response content is rendered as plain text without markdown processing. Users see raw
**bold**instead of formatted bold text. -
Do NOT pass when: A markdown library is installed but the message component does not use it — having
react-markdowninpackage.jsonwithout importing it in the message renderer does not count as pass. -
Skip (N/A) when: The application is documented as a non-markdown interface (e.g., a pure voice assistant or structured-data-only output). Signal: no markdown-related dependencies and response display is deliberately plain text.
-
Detail on fail:
"Message content rendered as plain text — no markdown processor found in dependencies; users see raw markdown syntax" -
Remediation: Add
react-markdownto your project. In your message component atsrc/components/chat/MessageBubble.tsx(or equivalent), wrap content:import ReactMarkdown from 'react-markdown'; <div className="prose dark:prose-invert"> <ReactMarkdown>{message.content}</ReactMarkdown> </div>If using Tailwind, the
@tailwindcss/typographyplugin provides clean markdown styling via theproseclass. Avoid rendering raw HTML from AI output without sanitization. -
Cross-reference: For a deeper analysis of accessible content rendering, the Accessibility Fundamentals Audit covers heading hierarchy and semantic HTML in detail.
External references
- wcag:2.2 · 1.3.1 — Info and Relationships
Taxons
History
- 2026-04-18·v1.0.0·Initial import from ai-chat-visibility·automated