Skip to content

JavaScript Tutorial JavaScript Security Basics

Cross-Site Scripting (XSS) Basics

Lesson 228 of 258 3 min read By Deepak Paswan Updated Oct 4, 2026

Cross-site scripting (XSS) is one of the most common web security problems. It happens when a website puts untrusted data (text from a user, a URL parameter, an API) into a page as if it were code, so a malicious visitor can make the page run their script in other people’s browsers.

This lesson is about defending against it.

Why it is serious

A script running on your page has the same powers as your own code. It can read what the user sees, change the page, send requests as the user, and read anything stored in the page’s localStorage. The user sees your site and trusts it, but the page is doing what someone else told it to.

The root cause

Data and code get mixed up:

index.html
HTML
<!-- Your code builds HTML from a comment typed by a visitor -->
commentBox.innerHTML = "<p>" + comment + "</p>";

If comment is plain text, everything is fine. If it contains HTML, the browser parses it as HTML, and that can include executable parts. The page cannot tell your markup from the visitor’s.

The three types (in short)

TypeWhere the bad data comes from
Stored XSSsaved on the server (a comment, a profile) and shown to other users
Reflected XSSpart of the request (a search term in the URL) echoed back in the response
DOM-based XSSJavaScript on the page takes data from the URL or elsewhere and puts it into the DOM unsafely

This course focuses on the part JavaScript controls: how you put data into the page.

The defences

  1. Treat all external data as untrusted: user input, URL parts, API responses, postMessage data, local storage, third-party content.
  2. Output text as text. Use textContent, not innerHTML: textContent vs innerHTML.
  3. Build elements with createElement rather than gluing HTML strings.
  4. Validate and encode on the server, which is the real security boundary.
  5. If you must allow HTML (a rich text comment), use a well-tested sanitizer library that removes dangerous parts. Do not write your own with regular expressions.
  6. Avoid dangerous APIs: eval(), new Function(), string arguments to setTimeout, document.write(), inline event handler attributes, javascript: URLs (DOM-based XSS).
  7. Add a Content Security Policy (CSP) as a second layer, so the browser refuses inline and unexpected scripts.
  8. Keep cookies safe: HttpOnly, Secure, SameSite, so injected script cannot read session cookies.
  9. Keep libraries updated.

A safe version

index.html
HTML
<ul id="comments"></ul>
<script>
  function addComment(text) {
    const li = document.createElement("li");
    li.textContent = text;                  // always treated as text
    document.querySelector("#comments").append(li);
  }

  addComment("Great article!");
  addComment("<b>Not bold</b>, just text with angle brackets");
</script>

The second comment appears with the angle brackets visible. Nothing is interpreted as HTML.

Defence in depth

No single rule is enough: use safe output and server-side validation and a CSP and safe cookies. If one fails, the others limit the damage.

Do not rely on client-side checks

Filtering on the front end is a courtesy. Attackers do not use your form. They send requests directly. The server must validate and encode too.

info
You will not learn attacks here
This chapter intentionally teaches the safe patterns. If you want to test your own site, use a proper security scanner and a test environment you own.