Working with XSS Protection
1. Understanding XSS Attack Vectors
| Type | Detail |
| Stored | Malicious script saved to DB, served to others |
| Reflected | From URL/form, immediately echoed |
| DOM-based | Client-side sink (innerHTML, eval) |
| Mutation (mXSS) | Sanitized HTML mutated by browser into XSS |
| Practice | Detail |
| Allowlist | Specific patterns (email regex, UUID) |
| Length cap | Reject oversized input early |
| Type check | Use schemas (Zod, Joi, Pydantic) |
| Not enough alone | Output encoding still required |
3. Using Output Encoding
| Context | Encoding |
| HTML body | & < > " ' → entities |
| HTML attribute | All non-alphanumeric → &#x..; |
| JS string | \xHH escaping |
| URL | percent-encoding |
| CSS | \HH escaping |
4. Implementing HttpOnly Cookie Flag
Prevents document.cookie read — XSS cannot exfiltrate session.
5. Using Content Security Policy
Example: Strict CSP
Content-Security-Policy:
default-src 'self';
script-src 'self' 'nonce-rAnd0m';
style-src 'self' 'nonce-rAnd0m';
img-src 'self' data: https:;
object-src 'none';
base-uri 'none';
frame-ancestors 'none';
require-trusted-types-for 'script';
Deprecated: X-XSS-Protection. Modern browsers ignore. Use strict CSP instead.
7. Handling DOM-Based XSS
| Sink | Safer Alternative |
| innerHTML | textContent / Trusted Types |
| eval / Function | Avoid; use JSON.parse |
| document.write | Avoid entirely |
| setTimeout(string) | setTimeout(fn) |
8. Implementing Sanitization Libraries
| Library | Use |
| DOMPurify | Browser/Node HTML sanitization (de-facto standard) |
| sanitize-html | Node, configurable allowlist |
| OWASP Java HTML Sanitizer | Java |
| bleach | Python |
9. Using Trusted Types
Example: Enforce Trusted Types
// CSP: require-trusted-types-for 'script'
const policy = trustedTypes.createPolicy("default", {
createHTML: s => DOMPurify.sanitize(s)
});
el.innerHTML = policy.createHTML(userInput); // raw string would throw
CHROMIUM — Firefox/Safari still partial.
10. Implementing Context-Aware Encoding
| Framework | Detail |
| React | JSX auto-encodes; only dangerouslySetInnerHTML is risky |
| Vue | {{ }} safe; v-html risky |
| Angular | Auto-sanitization with DomSanitizer |
| Templates | Use auto-escaping engines (Twig, Jinja, Handlebars) |