Definition · Security Headers
What is Cross-Site Scripting?
Cross-site scripting happens when untrusted input reaches a browser in a context where it is interpreted as code rather than data. Because the injected script runs in the origin of the vulnerable site, it inherits that origin’s privileges: it can read the DOM, make authenticated requests with the user’s cookies, rewrite the page, and capture anything typed into it. XSS has appeared in every edition of the OWASP Top Ten in one form or another.
The three classic forms
- Reflected — the payload arrives in the request, typically a query parameter, and is echoed straight back in the response. Exploitation needs the victim to follow a crafted link.
- Stored — the payload is persisted, in a comment, profile field or log viewer, and served to everyone who views it later. The most damaging, because it needs no per-victim delivery.
- DOM-based — the vulnerability is in client-side JavaScript that writes untrusted data into a dangerous sink such as
innerHTMLoreval. The server-side response may be entirely innocent, which is why server-focused testing misses it.
Why it is hard to eliminate
Correct handling depends on context. The escaping needed inside an HTML element differs from an attribute, a URL, a CSS value and a JavaScript string literal, and a value that passes through several of those needs care at each step. Modern frameworks escape by default and prevent the majority of cases, but they also provide deliberate escape hatches — dangerouslySetInnerHTML, v-html, template SafeString — and those are where the bugs concentrate. Rich-text features, javascript: URLs assembled from user data, and HTML emails rendered in an application add further surface.
Controls that hold up
Contextual output encoding at the point of rendering is the primary fix, with framework auto-escaping doing the work wherever possible and a vetted sanitiser used for HTML that genuinely must be accepted. On top of that, CSP provides real defence in depth: a policy without unsafe-inline, using nonces or hashes and ideally strict-dynamic, stops injected script from executing even when an injection point exists. Marking session cookies HttpOnly keeps them out of reach of script, and SameSite limits what a stolen session can be used for elsewhere.
Finding XSS reliably needs application-level testing — DAST and SAST tooling, and penetration testing for the cases automation cannot reach. External scanning of an attack surface establishes something narrower but still useful: which hosts lack a CSP at all, and therefore have no second line of defence if an injection is found.
Related concepts
See CSP, clickjacking, CORS misconfiguration, subresource integrity and security headers.