XSS Prevention
Reflected, stored, DOM XSS types, sanitization, CSP, framework protections.
securityfrontendbackend
# XSS Prevention
## Three types
1. **Reflected**: Malicious input in URL reflected back in HTML.
2. **Stored**: Malicious input saved to DB, served to other users.
3. **DOM-based**: Client JS writes untrusted data to DOM.
## Framework auto-escaping
React, Vue, Angular all auto-escape by default:
```tsx
// SAFE: React escapes this
<p>{userInput}</p>
// DANGEROUS: bypasses escaping
<div dangerouslySetInnerHTML={{ __html: userInput }} />
```
Never use `dangerouslySetInnerHTML` / `v-html` / `innerHTML` with untrusted data.
## Server-side sanitization
```ts
import DOMPurify from 'isomorphic-dompurify'
// Allow only safe HTML tags
const clean = DOMPurify.sanitize(rawHtml, {
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a', 'p', 'br'],
ALLOWED_ATTR: ['href'],
})
```
## Content Security Policy (CSP)
```
Content-Security-Policy:
default-src 'self';
script-src 'self' 'nonce-abc123';
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
connect-src 'self' https://api.example.com;
frame-ancestors 'none';
```
Next.js: set in `next.config.js` headers or middleware.
## Input validation rules
```ts
// Always validate on SERVER (client validation is UX only)
const schema = z.object({
name: z.string().min(1).max(100),
email: z.string().email(),
bio: z.string().max(500).transform(s => DOMPurify.sanitize(s)),
})
```
## Checklist
- [ ] Never insert untrusted data into raw HTML.
- [ ] Use CSP headers in production.
- [ ] Sanitize rich-text/markdown before rendering.
- [ ] Set `HttpOnly`, `Secure`, `SameSite` on cookies.
- [ ] Encode URL parameters: `encodeURIComponent()`.
- [ ] Use `textContent` not `innerHTML` for dynamic text.
API: /api/skills/xss-prevention