Imagine visiting a perfectly normal website -- your favorite forum, an online store, or a news site -- and without realizing it, your browser quietly executes a malicious script that steals your session cookie and sends it to an attacker. You never clicked anything suspicious. You never downloaded a file. The website itself was the weapon. This is the reality of cross-site scripting, commonly known as XSS, and it remains one of the most widespread vulnerabilities on the web.
XSS exploits the trust that a browser places in the content served by a website. When a site fails to properly handle user input, an attacker can slip their own code into the page. Every visitor who loads that page then unknowingly runs the attacker's script. Understanding how this works is essential whether you build websites or simply browse them.
How Cross-Site Scripting Works
At its core, XSS takes advantage of a simple problem: a website includes untrusted data in its output without properly cleaning or encoding it first. Here is a basic example. Suppose a site has a search feature that displays the user's query back on the results page. If a user searches for sneakers, the page might render something like "You searched for: sneakers." But what if someone enters a search query that contains a snippet of JavaScript instead of normal text? If the site does not sanitize that input, the browser will interpret the injected code as part of the page and execute it.
That injected script can do almost anything the legitimate page scripts can do. It can read cookies, access form data, redirect the user to a phishing site, or even modify the content of the page in real time. Because the malicious code runs in the context of the trusted site, the browser has no reason to block it.
The Three Main Types of XSS
Not all XSS attacks work the same way. They fall into three categories, each with different delivery mechanisms and severity levels.
Reflected XSS is the most common type. The malicious script is embedded in a link -- often sent via email, a chat message, or a social media post. When the victim clicks the link, the script is "reflected" off the web server and executed in the victim's browser. The payload is not stored anywhere on the server. It only fires when the victim follows the crafted URL, making it a one-shot attack that relies on social engineering to deliver.
Stored XSS is more dangerous because the malicious script is permanently saved on the target server -- typically in a database, a comment field, a forum post, or a user profile. Every visitor who views the affected page will execute the attacker's code without needing to click a special link. A single stored XSS vulnerability in a popular forum thread could compromise thousands of users.
DOM-based XSS occurs entirely on the client side. Instead of the server reflecting or storing the malicious input, the vulnerability lives in the page's own JavaScript code. If a client-side script reads data from the URL (such as a hash fragment or query parameter) and writes it into the page without sanitization, an attacker can manipulate that data to inject executable code. The server never sees the payload, which makes this type harder to detect with traditional server-side security tools.
What Attackers Can Do with XSS
The impact of a successful XSS attack depends on the context, but the possibilities are broad and serious:
- Session hijacking. By stealing a user's session cookie, the attacker can impersonate the victim and access their account without needing a password.
- Credential theft. The injected script can create a fake login form overlay on the real page, tricking users into entering their username and password directly into the attacker's hands.
- Malware delivery. XSS can redirect visitors to malicious sites that attempt to install harmful software on their devices.
- Defacement and misinformation. An attacker can alter the visible content of a page, spreading false information or damaging the site's reputation.
- Keylogging. A script running on the page can record everything a user types, capturing sensitive data in real time.
Because the malicious code executes within the trusted origin of the vulnerable site, users and their browsers have no easy way to distinguish it from legitimate functionality.
How Websites Can Prevent XSS
The good news is that XSS is a well-understood vulnerability with effective defenses. The challenge is applying them consistently across every input and output point on a site.
Sanitize and validate all input. Every piece of data that comes from a user -- form fields, URL parameters, headers, cookies -- should be treated as potentially hostile. Validate that input matches the expected format and reject anything that does not.
Encode output properly. When displaying user-supplied data on a page, encode it so that the browser treats it as text rather than executable code. HTML encoding, JavaScript encoding, and URL encoding each serve different contexts, and using the right one for each situation is critical.
Implement a Content-Security-Policy. A strong CSP header is one of the most effective defenses against XSS. It tells the browser which sources of scripts, styles, and other resources are allowed to load. A well-configured CSP can block inline scripts entirely, which neutralizes most XSS payloads even if the attacker manages to inject code into the page. You can check whether a site has CSP and other critical headers using our HTTP headers checker.
Use HTTP-only and secure cookie flags. Marking session cookies as HttpOnly prevents JavaScript from accessing them, which blocks the most common XSS exploit -- session hijacking. The Secure flag ensures cookies are only sent over HTTPS connections, and enforcing HSTS ensures that those encrypted connections are never downgraded.
Adopt a modern framework. Most contemporary web frameworks -- React, Angular, Vue, and others -- automatically escape output by default. While developers can still introduce vulnerabilities by using features that bypass escaping, the baseline protection is significantly better than manually building HTML strings.
How Users Can Protect Themselves
You do not need to be a developer to reduce your risk from XSS attacks. A few practical habits make a meaningful difference.
Be cautious with links. Reflected XSS relies on getting you to click a crafted URL. If a link in an email or message looks unusual, or if the URL contains a suspicious amount of encoded characters, think twice before clicking. Run it through a Link safety checker first.
Keep your browser updated. Modern browsers include built-in protections that can mitigate certain types of XSS. Staying current ensures you have the latest defenses active.
Use browser extensions wisely. Script-blocking extensions can prevent unauthorized JavaScript from running, though they may break some site functionality. Finding the right balance depends on your tolerance for inconvenience versus your need for security.
Watch for unexpected behavior. If a normally trustworthy website suddenly looks different, asks you to log in again when you should already be authenticated, or redirects you somewhere unexpected, treat it as a warning sign. Close the tab and navigate to the site directly by typing the address yourself.
Staying Ahead of XSS
Cross-site scripting has been a top web security concern for over two decades, and it shows no signs of disappearing. The fundamental issue -- trusting user input -- is easy to understand but surprisingly difficult to eliminate across every corner of a complex application. For site owners, the combination of input validation, output encoding, and a strong Content-Security-Policy provides a robust defense. For everyday users, a healthy dose of skepticism toward unfamiliar links and a habit of keeping software up to date go a long way. The web is built on trust between browsers and servers, and understanding how XSS exploits that trust is the first step toward keeping it intact.

