Cross-site scripting (XSS) happens when an application includes user-supplied data in a web page without proper encoding. The browser can't distinguish between the application's legitimate scripts and the attacker's injected code, so it executes both.
The impact can be significant: attackers can steal session tokens, capture credentials, redirect users to malicious sites, or perform actions on behalf of logged-in users. Unlike SQL injection, which targets the server, XSS targets the browser, exploiting trust between users and the application.
XSS is catalogued as CWE-79 and consistently appears in the OWASP Top 10.
Types of XSS
-
Reflected XSS involves malicious input that's immediately echoed back in the response, like a search term displayed on a results page. In this attack, the attacker tricks a user into clicking a crafted link.
-
Stored XSS is worse. The malicious payload gets saved (in a database, comment field, etc.) and served to every user who views that content. A single injection can affect thousands of users.
-
DOM-based XSS happens entirely in the browser, when client-side JavaScript uses untrusted data in unsafe ways.
Prevention
Output encoding is the primary defense for XSS attacks. User-supplied content should be escaped before rendering: HTML entities for HTML context, JavaScript escaping for script context, URL encoding for URLs. The OWASP XSS Prevention Cheat Sheet covers context-specific encoding in detail.
Modern frontend frameworks (React, Vue, Angular) generally handle encoding automatically when you use their templating correctly. The vulnerabilities creep in when developers use "escape hatches" like dangerouslySetInnerHTML or bypass the framework with raw DOM manipulation.
Content Security Policy (CSP) headers provide defense in depth by restricting where scripts can load from and whether inline scripts are allowed.
AI-Generated XSS
AI agents can generate XSS vulnerabilities, particularly when building features that display user content. An agent might echo input directly without encoding, use innerHTML when textContent would be safer, or construct HTML through string concatenation.
These patterns are common enough that they're included in Corridor's default guardrails, flagging unsafe output handling before the code is committed.