// web security

Cross-Site Scripting (XSS): Types, Attacks & Defense

Cross-Site Scripting (XSS) explained

Cross-site scripting (XSS) has been in the OWASP Top 10 for two decades and is still everywhere. It lets an attacker run their JavaScript in your users’ browsers — stealing sessions, harvesting credentials and rewriting pages. This guide explains the three types, how they are exploited, and how to defend against them.

What XSS actually is

XSS happens when an application takes attacker-controlled input and includes it in a page without proper encoding, so the browser executes it as code instead of displaying it as text. The victim’s browser trusts your domain, so the injected script runs with full access to their session on your site.

The three types

  • Reflected XSS: the payload is in the request (e.g. a search term) and echoed straight back in the response. Exploited by tricking a victim into clicking a crafted link.
  • Stored XSS: the payload is saved by the app — in a comment, profile or message — and served to every user who views it. The most dangerous type, because it needs no lure and can hit many users, including admins.
  • DOM-based XSS: the vulnerability is entirely in client-side JavaScript that writes untrusted data into the page. It never touches the server in a way a server-side filter would catch, which is why modern front ends need dedicated testing.

What an attacker can do

  • Steal session cookies or tokens and hijack accounts.
  • Log keystrokes on a login form to harvest credentials.
  • Perform actions as the victim (transfer funds, change email) via forged requests.
  • Deface pages or inject convincing phishing content on your trusted domain.

Stored XSS in an admin panel is a common path to full application takeover: one malicious record, viewed by an administrator, runs attacker code in an admin session.

How to prevent it

  • Context-aware output encoding — the primary defence. Encode data for the exact context (HTML, attribute, JavaScript, URL) where it is rendered.
  • Use frameworks safely — React, Angular and Vue auto-escape by default; the risk is in escape hatches like dangerouslySetInnerHTML.
  • Content Security Policy (CSP) — a strong second layer that limits what scripts can run even if injection slips through.
  • HttpOnly cookies so injected script cannot read session tokens directly.
  • Validate input, but never rely on input filtering alone — encoding on output is what stops XSS.

How we test for it

We probe every input that reaches the page — reflected, stored and DOM sinks — with context-specific payloads, then prove genuine impact such as session theft rather than just popping an alert box. DOM XSS in particular needs manual review of client-side code, which is central to single-page application testing. XSS testing is a core category of any web application penetration test, and dedicated coverage lives in XSS testing.

Frequently asked questions

Is an alert box a real finding? It’s a proof of concept. A good report shows the actual impact — cookie theft or account actions — not just alert(1).

Does a CSP make us immune? No, but a well-tuned CSP dramatically limits exploitation and is strongly recommended alongside output encoding.

Want every injection point in your app tested by hand? Explore XSS testing or get a fixed-price quote.

// get started

Work with AgentOffense

Tell us about your target and goals. We’ll reply with scope and a fixed-price quote — usually within one business day.

./request_engagement