Explain the difference between output escaping (context-specific encoding) and sanitizing user input (allowlist filtering). Include when to use each, how they work, and why both matter for XSS prevention.
Use this JavaScript interview question to rehearse a quick answer, common mistake, follow-up, and production pitfall.
Escaping vs Sanitizing: What's the Difference?Frontend interview answer
This JavaScript interview question tests whether you can explain Escaping vs sanitizing: what is the difference, connect it to production trade-offs, and handle common follow-up questions.
- Escaping vs sanitizing: what is the difference explanation without falling back to memorized docs wording
- Security and Html reasoning, edge cases, and production failure modes
- How you would answer the most likely JavaScript interview follow-up
Big idea
Escaping and sanitizing both reduce XSS risk, but they solve different problems. Escaping encodes characters so the browser treats user input as text in a specific output context. Sanitizing removes or rewrites dangerous parts of user-provided markup so some HTML can be allowed.
Aspect | Escaping | Sanitizing |
|---|---|---|
Primary goal | Encode special characters so they render as text | Allow some HTML while blocking dangerous tags/attrs |
Input expectation | Plain text | HTML-like input |
Context | Context-specific (HTML text, attributes, URLs, JS, CSS) | HTML context only |
Typical tooling | textContent, template auto-escaping, encoding helpers | DOMPurify, browser sanitizer APIs, server allowlists |
Failure mode | Wrong encoder for the context can still allow XSS | Weak allowlist can allow XSS or strip too much content |
Real-world scenario
A profile bio can be plain text (escape and render safely), but a blog editor might allow limited rich text (sanitize with an allowlist). Decide based on the product requirement, not convenience.
const userInput = '<img src=x onerror=alert(1) />';
// Escaping (text only)
bioEl.textContent = userInput;
// Sanitizing (allow some HTML)
bioEl.innerHTML = DOMPurify.sanitize(userInput, {
ALLOWED_TAGS: ['b', 'i', 'a'],
ALLOWED_ATTR: ['href', 'rel', 'target']
});
Context | Use | Example |
|---|---|---|
HTML text | textContent / template escaping | el.textContent = userText |
HTML attribute | Set attributes with encoded values | el.setAttribute('title', safeText) |
URL | Allowlist protocols + URL parsing | new URL(input, location.origin) |
JS string | Avoid inline JS; never concatenate user input | Prefer data attributes or JSON |
Common pitfalls
- Stripping tags with regex (easy to bypass).
- Sanitizing once and reusing the result in a different context.
- Double-escaping by encoding the same value twice.
- Storing only sanitized HTML and losing the original data.
Escape for the specific output context. Sanitize only when you must allow markup, and pair it with defense-in-depth like CSP and Trusted Types.
Use this as one explanation rep, then continue with the JavaScript interview questions cluster or a guided prep path.