API-005 critical general

XSS prevention

User-generated content is escaped or sanitized before rendering to prevent script injection

Question to ask

"Could a user store a script that runs in another user's browser?"

Verification guide

Severity: Critical

User-generated content must be escaped/sanitized before rendering to prevent script injection.

Check automatically:

  1. Check framework (many auto-escape by default):
# React/Vue/Angular (auto-escape by default)
grep -E "\"react\"|\"vue\"|\"@angular/core\"|\"svelte\"|\"solid-js\"" package.json 2>/dev/null

# Server-side templating (check escape mode)
grep -E "\"ejs\"|\"pug\"|\"handlebars\"|\"mustache\"|\"nunjucks\"" package.json 2>/dev/null
grep -E "jinja2|django|mako" requirements*.txt 2>/dev/null
  1. Check for dangerous bypass patterns:
# React dangerouslySetInnerHTML
grep -rE "dangerouslySetInnerHTML" src/ app/ components/ --include="*.tsx" --include="*.jsx" 2>/dev/null

# Vue v-html directive
grep -rE "v-html" src/ app/ components/ --include="*.vue" 2>/dev/null

# Angular innerHTML binding
grep -rE "\[innerHTML\]" src/ app/ --include="*.html" --include="*.ts" 2>/dev/null

# Direct innerHTML assignment
grep -rE "\.innerHTML\s*=" src/ app/ --include="*.ts" --include="*.js" 2>/dev/null

# jQuery html()
grep -rE "\.html\(" src/ app/ --include="*.ts" --include="*.js" 2>/dev/null
  1. Check for sanitization libraries:
# Sanitization libraries (good sign if dangerous patterns exist)
grep -E "\"dompurify\"|\"sanitize-html\"|\"xss\"|\"isomorphic-dompurify\"|\"js-xss\"" package.json 2>/dev/null

# Python sanitization
grep -E "bleach|html\.escape|markupsafe" requirements*.txt 2>/dev/null

# Sanitization usage
grep -rE "DOMPurify\.sanitize|sanitizeHtml|xss\(|escape\(" src/ app/ --include="*.ts" --include="*.js" 2>/dev/null
  1. Check for user content rendering:
# User content fields being rendered (manual review needed)
grep -rE "user\.bio|user\.description|comment\.content|post\.body|message\.text" src/ app/ components/ 2>/dev/null | head -10

# Markdown rendering (often allows HTML)
grep -E "\"marked\"|\"markdown-it\"|\"remark\"|\"showdown\"" package.json 2>/dev/null
grep -rE "marked\(|markdownIt|renderMarkdown" src/ app/ 2>/dev/null
  1. Check Content-Security-Policy (defense in depth):
# CSP headers in code
grep -rE "Content-Security-Policy|contentSecurityPolicy|helmet" src/ app/ lib/ 2>/dev/null

# Next.js CSP config
grep -rE "contentSecurityPolicy" next.config.* 2>/dev/null

Ask user:

  • "What frontend framework do you use?"
  • "Is there any user-generated content that's rendered as HTML?"
  • "Do you use a markdown renderer? Does it allow HTML?"

Cross-reference with:

  • Section 32 (Content Security Policy - defense in depth)
  • API-003 (input validation)
  • CSS-001 (HttpOnly cookies - XSS can't steal them)

Pass criteria:

  • Framework with auto-escaping (React, Vue, Angular, Svelte)
  • Dangerous bypasses only used with sanitized content (DOMPurify, sanitize-html)
  • OR no user-generated content rendered as HTML

Fail criteria:

  • dangerouslySetInnerHTML with unsanitized user content
  • v-html with unsanitized user content
  • Direct .innerHTML assignment from user input
  • Markdown rendered without HTML sanitization

Evidence to capture:

  • Frontend framework (and whether it auto-escapes)
  • Dangerous patterns found and whether sanitized
  • Sanitization library used (if any)
  • CSP headers present (defense in depth)

Section

31. API Design

API & Security