← All cybersecurity posts

Cross-Site Scripting (XSS): Types, Examples and Prevention

Cross-site scripting (XSS) lets an attacker run their own JavaScript in another user's browser, inside your application. That script can do anything the user can: read data, change settings, or steal tokens.

The three main types

Reflected XSS

Input from the request is immediately echoed back into the page without encoding.

https://app.example.com/search?q=<script>alert(document.domain)</script>

The attacker sends a crafted link to a victim. When the victim clicks it, the script runs.

Stored XSS

Malicious input is saved, for example in a comment, profile name or support ticket, and executes for everyone who views it. Stored XSS in a place admins view, such as a support dashboard, is especially dangerous.

DOM-based XSS

The vulnerability lives entirely in client-side JavaScript, which reads attacker-controlled data, such as location.hash, and writes it into the page unsafely.

// Vulnerable
document.getElementById("greeting").innerHTML = location.hash.slice(1);

What attackers do with XSS

  • Perform actions as the victim, such as changing their email or creating API keys.
  • Read sensitive data displayed on the page.
  • Steal tokens stored in localStorage.
  • Show fake login prompts to capture passwords.
  • Spread to other users via stored payloads.

XSS in modern frameworks

React, Vue and Angular escape output by default, which prevents most XSS. It still happens through:

  • dangerouslySetInnerHTML in React, or v-html in Vue, with untrusted content.
  • Rendering Markdown or rich text without sanitising the HTML output.
  • href attributes with javascript: URLs built from user input.
  • Server-rendered templates that bypass the framework.
  • Third-party scripts and widgets with their own vulnerabilities.

How to prevent XSS

  1. Rely on framework escaping and avoid raw HTML insertion.
  2. Sanitise rich content with a well-maintained library such as DOMPurify before rendering it as HTML.
  3. Validate URLs and only allow http: and https: schemes in user-supplied links.
  4. Use a Content Security Policy to limit where scripts can load from and block inline scripts.
  5. Set cookies HttpOnly so session cookies cannot be read by JavaScript.
  6. Encode for context: HTML body, attribute, JavaScript and URL contexts need different encoding.
import DOMPurify from "dompurify";
const safe = DOMPurify.sanitize(userHtml);

Testing for XSS

Effective XSS testing submits payloads into every input, follows where the data is rendered, including admin views and emails, and checks each output context. Automated agents can track stored input across pages that a quick manual test may miss.

SecurityInfinity tests for reflected, stored and DOM-based XSS, verifies execution, and points to the exact rendering code to fix. Start free.

Frequently asked questions

Is XSS still a serious vulnerability?

Yes. XSS can lead to account takeover, especially when it affects admins or when tokens are accessible to JavaScript.

Does a Content Security Policy prevent XSS?

A strict CSP significantly limits the impact of XSS, but it is a second layer. Fixing the underlying output handling is still required.

Is self-XSS a real vulnerability?

Self-XSS, where a user can only attack themselves, is usually low severity unless it can be combined with another bug, such as CSRF, to target others.

Find what attackers can see, before they do.

AI pentesting agents test your web app, API and cloud, and every finding comes with evidence and a fix. First report in about 10 minutes.

Stay ahead of attackers.

New vulnerabilities, breach write-ups and practical fixes. A few emails a month.