← Concepts

阅读中文版本

Cross-Site Scripting (XSS)

XSS injects attacker-controlled script into a page viewed by others. Output encoding, safe DOM APIs, and CSP limit execution, while input validation alone is insufficient.

security

Definition

Cross-Site Scripting is a vulnerability where untrusted data is interpreted as executable code in a victim's browser. In reflected XSS the payload comes from the current request; in stored XSS it is persisted and served to later visitors; in DOM XSS the client-side code writes untrusted data into a dangerous sink such as innerHTML. The impact includes session theft, action forgery, credential phishing, and data exfiltration.

Context and scope

XSS applies wherever applications render user or third-party content, including comments, profiles, search results, markdown previews, and admin dashboards. It is prevented primarily at output time by encoding data for the correct context and by avoiding dangerous APIs, with CSP as defense in depth.

Common misconceptions

  • Input validation alone prevents XSS — the same value may be safe in one context and dangerous in another; output encoding is required
  • React escapes everything — dangerouslySetInnerHTML and unvalidated URLs bypass escaping
  • CSP makes XSS impossible — CSP reduces impact and blocks many payloads, but misconfigurations and allowed origins can still permit execution

Anti-patterns

  • Building HTML with string concatenation and inserting it with innerHTML
  • Putting untrusted values into href, src, or style attributes without protocol validation
  • Storing HTML from users and rendering it without sanitization

Related concepts

Related examples

Authoritative source

https://owasp.org/www-community/attacks/xss/

Three delivery paths

Reflected XSS echoes a request value into the response. Stored XSS persists the payload and serves it to later users. DOM XSS occurs when client code moves untrusted data into a dangerous sink without server involvement.

Prevent at the sink

// ❌ HTML injection
container.innerHTML = `<p>${userInput}</p>`;

// ✅ textContent treats the value as text
const p = document.createElement('p');
p.textContent = userInput;
container.append(p);

When HTML is genuinely required, sanitize with a maintained allowlist library and encode for the exact context. Validate URL schemes before assigning to href or src; allow only https:, mailto:, and explicitly approved schemes.

Defense in depth

  • Encode output for HTML, attributes, JavaScript, CSS, and URLs.
  • Use safe framework APIs and avoid raw HTML sinks.
  • Set a restrictive Content Security Policy with nonces or hashes.
  • Set cookies HttpOnly so script cannot read session cookies.
  • Sanitize markdown and rich text with a vetted library.

When it matters most

Any page that displays content from another user or an external system is a candidate. Compared to CSRF, XSS attacks the user’s trust in the page itself and can read data the user can see; CSRF causes actions without reading responses. Both require context-aware defenses, not a single global filter.

Pitfalls

Blacklist filtering of <script> misses event handlers, SVG, and encoded payloads. Escaping once and then decoding later reopens the hole. Storing unsanitized HTML and relying on the client to clean it shifts the vulnerability to every consumer.