Cybersecurity Terms

Cross-Site Scripting (XSS)

Cross-site scripting (XSS) is a web security vulnerability where an attacker injects malicious scripts into web pages viewed by other users. When a victim's browser executes the injected script, the attacker can steal session tokens, redirect users to malicious sites, deface web content, or perform actions on behalf of the victim. XSS exploits the trust a user's browser places in the content delivered by your application.

What is cross-site scripting?

Cross-site scripting, or XSS, is an attack where someone injects malicious JavaScript into your web application that then executes in another user's browser. The name is misleading (there's no "cross-site" component in most attacks), but the impact is concrete: the attacker's script runs with the same permissions as your legitimate application code.

When a user's browser loads a page from your application, it trusts everything on that page. If an attacker can get their script onto your page, the browser treats it as part of your application. That script can then:

  • Steal session cookies and authentication tokens, letting the attacker impersonate the user
  • Capture keystrokes, including passwords and credit card numbers typed into forms
  • Modify page content, showing fake login forms or misleading information
  • Make API calls on behalf of the user, performing actions they never intended
  • Redirect users to malicious sites for further exploitation

Types of XSS

There are three main variants, each with a different attack mechanism:

  1. Stored (persistent) XSS. The malicious script is permanently stored on the target server, typically in a database field, forum post, comment, or user profile. Every user who views the affected page executes the attacker's script. This is the most dangerous type because it doesn't require tricking each victim individually. If your application stores user input and displays it to other users without proper encoding, you're vulnerable.
  2. Reflected XSS. The malicious script is embedded in a URL or form submission and reflected back in the server's response. The attacker tricks a victim into clicking a crafted link (often via phishing or social engineering). The server includes the malicious input in its response, and the victim's browser executes it. Search results pages and error messages are common targets.
  3. DOM-based XSS. The vulnerability exists entirely in client-side JavaScript. The application takes data from an attacker-controllable source (like the URL fragment or a query parameter) and writes it into the page's Document Object Model (DOM) without sanitization. The server never sees the malicious payload, which makes this type invisible to server-side security controls.

Why XSS matters for startups

Cross-site scripting is consistently the most commonly discovered web vulnerability class. MITRE CWE classifies it as CWE-79 (Improper Neutralization of Input During Web Page Generation), and the OWASP Top 10:2025 includes it under the Injection category. HackerOne reports that XSS accounts for roughly 20% of all vulnerabilities submitted to bug bounty programs, making it the #1 most commonly reported vulnerability type on their platform.

Here's why startups should care:

  1. It's the vulnerability most likely in your application right now. XSS is so common because every place your application renders user-supplied data is a potential vulnerability. Comment fields, user profiles, search results, error messages, URL parameters, form inputs: if your application displays content that a user (or attacker) provided, XSS is a risk.
  2. Modern frameworks help but don't eliminate it. React, Vue, and Angular escape output by default, which prevents many XSS attacks. But every framework provides escape hatches: React's dangerouslySetInnerHTML, Vue's v-html directive, Angular's bypassSecurityTrust methods. The moment a developer uses one of these with user-controlled data, the framework's protections are bypassed. AI coding tools are particularly prone to using these unsafe patterns.
  3. XSS can chain into more serious attacks. On its own, XSS steals sessions and captures input. Combined with other vulnerabilities, it becomes a pivot point for deeper compromise. An XSS vulnerability that steals an admin's session token gives the attacker admin access to your application. An XSS that captures API keys in a developer tool can compromise your infrastructure.
  4. CISA considers it a design-level defect. In September 2024, CISA and the FBI issued a Secure by Design alert specifically about cross-site scripting, urging software manufacturers to eliminate XSS by adopting output encoding as a default behavior rather than leaving it to individual developers.

Preventing cross-site scripting

XSS prevention comes down to one principle: never trust user input, and always encode output.

  • Encode output based on context. HTML entity encoding prevents scripts from executing in HTML contexts. JavaScript encoding is needed for data inserted into JavaScript. URL encoding is needed for data placed in URL parameters. The OWASP XSS Prevention Cheat Sheet covers context-specific encoding in detail.
  • Use a Content Security Policy (CSP). A CSP header tells the browser which sources of scripts are legitimate. A well-configured CSP blocks the execution of injected inline scripts, even if an attacker gets their code onto your page. Start with a restrictive policy and loosen only as needed.
  • Lean on your framework's defaults. If you're using React, Vue, or Angular, their default output encoding handles most cases. The critical discipline is avoiding unsafe rendering methods with user-controlled data. Treat dangerouslySetInnerHTML and its equivalents as security-sensitive code that requires review.
  • Sanitize HTML when you must allow it. If your application genuinely needs to render user-provided HTML (like a rich text editor), use a sanitization library like DOMPurify to strip dangerous elements and attributes while preserving safe formatting.
  • Set the HttpOnly flag on session cookies. This prevents JavaScript from accessing the cookie, which means even if XSS is exploited, the attacker can't steal the session token directly. It's not a fix for XSS, but it limits the damage significantly.
  • Scan for XSS in development and at runtime. Static analysis catches dangerous patterns in your source code (like unsafe use of dangerouslySetInnerHTML). Dynamic testing sends XSS payloads against your running application to find reflected and stored XSS that code analysis can miss.

How Fencer helps with cross-site scripting

Fencer's SAST scanning detects XSS-prone code patterns in your repositories, including unsafe rendering methods and missing output encoding. Fencer's DAST scanning tests your running application with XSS payloads to find reflected and stored XSS vulnerabilities that are actually exploitable. Findings appear inline in your pull requests so developers can fix XSS before it ships, rather than discovering it in a pen test months later.

Frequently asked questions

Does using React or another modern framework protect against XSS?

Modern frameworks like React, Vue, and Angular provide significant XSS protection through automatic output encoding. React escapes values embedded in JSX by default, and Vue escapes content in template expressions. However, this protection has limits. Any use of dangerouslySetInnerHTML (React), v-html (Vue), or bypassSecurityTrustHtml (Angular) with user-controlled data bypasses the framework's protections entirely. Third-party libraries that manipulate the DOM directly can also introduce XSS. Treat your framework's defaults as a strong foundation, not a guarantee, and scan your code for unsafe rendering patterns.

Toggle answer

What's the difference between XSS and SQL injection?

Both are injection attacks, but they target different layers. SQL injection targets your server's database by injecting malicious database queries through user input. XSS targets your users' browsers by injecting malicious JavaScript through your application's output. SQL injection compromises your data. XSS compromises your users. The defenses are different too: SQL injection is prevented by parameterized queries (separating commands from data on the server), while XSS is prevented by output encoding (separating code from data in the browser). Both are in the OWASP Top 10 Injection category, and most applications should be testing for both.

Toggle answer

Is XSS still relevant with single-page applications?

Yes, and in some ways more so. Single-page applications (SPAs) that handle routing and rendering in the browser are particularly susceptible to DOM-based XSS, where the vulnerability exists entirely in client-side JavaScript and never touches the server. Traditional server-side XSS protections (like WAFs) can't catch DOM-based XSS because the malicious payload never appears in a server request. If your SPA reads data from the URL, query parameters, or the hash fragment and writes it to the page without sanitization, you have a DOM-based XSS vulnerability that server-side scanning will miss. DAST tools that execute JavaScript and test the rendered DOM are essential for catching these.

Toggle answer

Secure your startup’s momentum