What is XSS and how do you prevent it?
Cross-Site Scripting (XSS) is a code injection vulnerability where an attacker injects malicious scripts into content served to other users. Unlike CSRF, which abuses the browser's trust in a session, XSS abuses the victim's trust in a website — the script runs in the origin of the target site and has full access to its DOM, cookies, and localStorage.
There are three main types:
**Reflected XSS:** Malicious input is immediately echoed back in the HTTP response without sanitization. The payload travels in a URL parameter; the victim is tricked into clicking the link. Common in search pages and error messages.
**Stored XSS:** The payload is persisted in the database (e.g., a comment, profile bio) and rendered for all users who view that resource. Higher severity because it requires no victim-specific link.
**DOM-based XSS:** The vulnerability lives entirely in client-side JavaScript. The page reads from an attacker-controlled source (e.g., `location.hash`, `document.referrer`) and writes it to a dangerous sink (`innerHTML`, `eval`, `document.write`) without sanitization. The server never sees the payload.
Prevention:
**Context-aware output encoding:** The most important defense. HTML-encode untrusted data before inserting it into HTML context (`&` → `&`, `<` → `<`). Use attribute encoding for HTML attributes, JavaScript encoding for script contexts, and URL encoding for URLs. Never mix encoding schemes for the wrong context.
**Use safe APIs:** Prefer `textContent` over `innerHTML`. In React/Vue/Angular, the framework auto-escapes by default — never use `dangerouslySetInnerHTML` or `v-html` with untrusted input. Template engines like Jinja2 auto-escape by default; mark trusted HTML explicitly.
**Content Security Policy (CSP):** A response header (`Content-Security-Policy: default-src 'self'`) that instructs browsers to only execute scripts from allowed sources. A strict CSP with nonces or hashes and no `'unsafe-inline'` is a strong second layer. It does not replace encoding but limits attacker impact even if encoding is missed.
**Input validation:** Validate format and type on input (e.g., reject `<` in a name field), but do not rely on this as the primary defense — encoding at output is more reliable.
**HttpOnly cookies:** Prevent JavaScript from reading session cookies, limiting cookie theft even if XSS fires. Combine with Secure and SameSite flags.
In practice: Django templates auto-escape, React auto-escapes JSX, but both have escape hatches that developers misuse. Code review should flag any raw HTML insertion. A CSP header adds defense-in-depth.
Correctly distinguishes at least two XSS types and explains output encoding as the primary defense with a concrete example.
Covers all three XSS types with accurate definitions, explains context-aware encoding, discusses CSP as defense-in-depth, mentions DOM sinks, and references how frameworks handle this.
Reading the answer is step one. Explaining it unprompted — under interview pressure — is what actually matters. Get AI-graded feedback on your answer with follow-up probes on your weak points.
Get Graded — Free Assessment