Application Security In progress
Beginner 18 min read Application Security
Cross-Site Scripting (XSS)
How the browser itself becomes the victim: reflected, stored, and DOM-based XSS, and the output-encoding rules that eradicate the class.
XSSreflectedstoredDOM XSSCSPoutput encodingsame-origin
Introduction
What is this?
XSS is an injection into the browser: attacker-controlled text is rendered as HTML/JS in a user's session, running with the privileges of the honest origin.
Motivation
Why do you need it?
- XSS converts a stored comment, a search echo, or a URL fragment into full session theft and keystroke capture.
- It is the sneakiest top-tier bug: the target audience is other users, not the database.
- Learning the three flavors (reflected, stored, DOM) generalizes to every templating engine you will ever use.
Think about it
Mental model
Imagine
A forum comment box
Think of
A guestbook where a page of <script> is bound in as a page
The book was meant for words; someone pasted instructions the future readers would execute.
Mechanics
How it works
- Reflected: input is printed unescaped in the response (search echo), attacker lures the victim via the crafted link.
- Stored: the payload is saved in the app (comment/profile) and rendered to every subsequent visitor — the most damaging.
- DOM XSS: the client-side JS reads a location/source and writes it into innerHTML without a sink guard.
- Same-origin policy is the fence; XSS hops it because the code executes within the honest origin's trust boundary.
A stored XSS lifecycle
Injectattacker posts <script> as a comment
StoreDB persists the payload
Renderunescaped output reaches the browser
Executepayload runs as the site's origin
Stealsession/keystroke data exfiltrated
Real world
In production
- A SaaS team enforces a 'encode-on-output' rule in every template, so even user-entered HTML is inert by default.
- A bank deploys a strict CSP that blocks inline scripts, making even a successful injection hard to weaponize.
- A bug bounty program rewards a report of stored XSS in a syntax highlighter; the fix ships as library pinning + escaping.
Guidelines
Best practices
- Encode output by context: HTML-encode text nodes, attribute-encode attributes, and JS-encode in script contexts.
- Prefer safe frameworks/building patterns that auto-escape (React, Vue templates, Rails erb) over innerHTML surgery.
- Add a strict Content-Security-Policy (no inline scripts, source allow-lists) as depth, not as a replacement for encoding.
- Treat any sink (innerHTML, document.write, eval) as a code-review checkpoint.
Watch out
Common mistakes
- Thinking 'I block <script>' is enough — payloads ride in event handlers, img src, and URL schemes.
- Escaping only the keyword in the middle of the string and leaving the surrounding HTML mechanics unguarded.
- Trusting 'the sanitizer library' forever without a critical-update process for it.
- Assuming innerHTML use in a React-incompatible widget escaped review because 'the app is modern'.
When things break
Debugging tips
- To triage quickly, echo input verbatim in a <textarea> and see whether it 'emerges' raw in the returned HTML.
- Browser devtools > Sources is your friend: break on the sink (innerHTML) to confirm DOM-XSS path.
- Test whether a pasted <img onerror=...> executes in a sandboxed viewer with JS disabled before enabling it.
Security
Security considerations
- Only verify XSS inside your own lab/own accounts; injecting scripts that affect real users is a crime, not a test.
- A stored XSS is also a data-processing event: keep logs of the test so forensics know your footprint.
- Pair XSS defense with session hardening (HttpOnly, Secure flags, SameSite) to cap the value of any theft.
Interviews
Interview checkpoint
Practice
Hands-on lab
Reflected, Stored, and DOM XSS in Your Own Juice Shop
50 min · beginner
Objectives
- Reflect XSS in Juice Shop's search field on your own instance.
- Store a payload that fires for later visitors.
- Apply the encoding fix in a scratch template and confirm it neutralizes the payload.
Reflected, Stored, and DOM XSS in Your Own Juice Shop
50 min · beginner
0/4 steps
0%
sandbox · Linux sandbox
$
Try these commands
Test yourself
Quick quiz
0/2
1
Stored XSS is worse than reflected because...
2
A strict CSP is best described as...
Go deeper