When AI response text is injected directly into the DOM via plain string interpolation, every **bold**, ## heading, and `code block` in the model's output renders as raw punctuation — a UX failure that signals a half-finished integration. Worse, some models emit markdown-formatted content specifically because they are prompted or fine-tuned to do so; stripping rendering creates a mismatch between what the model produces and what the user sees. OWASP LLM05 identifies trust and safety failures in output presentation as a category of harm; showing raw syntax characters where formatted prose was intended degrades user trust and undermines the inference-contract between model and interface.
Critical because raw markdown syntax in a user-facing interface is both a visible defect and a signal that the AI integration was never tested end-to-end with real model output.
Install react-markdown with GFM support and replace any plain string interpolation of AI output:
import ReactMarkdown from 'react-markdown'
import remarkGfm from 'remark-gfm'
// Replace: <p>{message.content}</p>
<ReactMarkdown remarkPlugins={[remarkGfm]}>
{message.content}
</ReactMarkdown>
For streaming responses, wrap in a component that buffers partial tokens before passing them to the renderer to avoid mid-token syntax artifacts.
ID: ai-response-quality.response-formatting.markdown-rendering-enabled
Severity: critical
What to look for: Enumerate all relevant files and Find all components that render AI-generated text. Check whether they use a markdown rendering library (react-markdown, marked, remark, rehype, mdx, etc.) or render raw text via plain string interpolation (which would expose raw **bold** and ## syntax to users). Check whether plain <p> tags or basic {response} interpolation is used without markdown processing. Quote the exact code pattern or configuration value found.
Pass criteria: At least 1 conforming pattern must exist. All AI response surfaces use a markdown rendering library or a purpose-built prose renderer. Headings, bold, italics, lists, and code blocks in AI output are rendered as formatted HTML, not shown as raw syntax characters.
Fail criteria: AI response text is rendered directly as plain text or via simple string interpolation without markdown processing, causing raw syntax characters to appear in the UI for users. A partial or incomplete implementation does not count as pass.
Skip (N/A) when: No AI SDK or AI API client is detected in package.json dependencies (openai, @anthropic-ai/sdk, ai, langchain, cohere-ai, etc.).
Cross-reference: For security evaluation of AI prompt handling and injection prevention, the AI Prompt Injection audit covers input sanitization and system prompt protection.
Detail on fail: "AI response rendered via {message.content} with no markdown library in ChatMessage.tsx — users see raw '**bold**' syntax" (max 500 chars)
Remediation: Install and wire in react-markdown (or equivalent) to process AI output before rendering:
npm install react-markdown remark-gfm
import ReactMarkdown from 'react-markdown'
import remarkGfm from 'remark-gfm'
// Before — raw text
<p>{message.content}</p>
// After — properly rendered markdown
<ReactMarkdown remarkPlugins={[remarkGfm]}>
{message.content}
</ReactMarkdown>
For streaming responses, ensure the markdown renderer handles partial content gracefully. The AI Chat Visibility Audit covers streaming UI patterns in more depth.