Web Security Fundamentals: XSS Prevention
Learn about Cross-Site Scripting (XSS) attacks and how to implement effective prevention strategies in modern web applications.
Web Security Fundamentals: XSS Prevention
Introduction
Cross-Site Scripting (XSS) remains one of the most common web security vulnerabilities. This guide explores different types of XSS attacks and provides practical prevention strategies for modern web applications.
Understanding XSS
Types of XSS Attacks
- Reflected XSS
- Stored XSS
- DOM-based XSS
Vulnerable Code Examples
Reflected XSS Example
javascript
// ❌ Vulnerable Codeapp.get('/search', (req, res) => { const query = req.query.q; res.send(` <h1>Search Results for: ${query}</h1> <div id="results">...</div> `);});Stored XSS Example
javascript
// ❌ Vulnerable Codeapp.post('/comments', (req, res) => { const comment = req.body.comment; db.comments.save({ text: comment, userId: req.user.id });});app.get('/comments', (req, res) => { const comments = db.comments.getAll(); res.send(` <div class="comments"> ${comments.map(c => `<div>${c.text}</div>`).join('')} </div> `);});DOM-based XSS Example
javascript
// ❌ Vulnerable Codeconst hash = window.location.hash.substring(1);document.getElementById('output').innerHTML = decodeURIComponent(hash);Prevention Strategies
1. Input Validation and Sanitization
typescript
// ✅ Secure Codeimport { sanitize } from 'dompurify';function validateAndSanitizeInput(input: string): string { // Remove any non-alphanumeric characters const alphanumeric = input.replace(/[^a-zA-Z0-9]/g, ''); // Sanitize HTML content return sanitize(alphanumeric);}app.post('/comments', (req, res) => { const sanitizedComment = validateAndSanitizeInput(req.body.comment); db.comments.save({ text: sanitizedComment, userId: req.user.id });});2. Output Encoding
typescript
// ✅ Secure Codefunction encodeHTML(str: string): string { return str .replace(/&/g, '&') .replace(/</g, '<') .replace(/>/g, '>') .replace(/"/g, '"') .replace(/'/g, ''');}app.get('/search', (req, res) => { const query = encodeHTML(req.query.q); res.send(` <h1>Search Results for: ${query}</h1> <div id="results">...</div> `);});3. Content Security Policy (CSP)
typescript
// ✅ Secure Codeapp.use((req, res, next) => { res.setHeader( 'Content-Security-Policy', "default-src 'self'; " + "script-src 'self' 'nonce-{RANDOM}' 'strict-dynamic'; " + "style-src 'self' 'unsafe-inline'; " + "img-src 'self' data: https:; " + "font-src 'self';" ); next();});4. Framework-specific Protection
React Example:
tsx
// ✅ Secure Codefunction SafeComponent({ userContent }: { userContent: string }) { // React automatically escapes content return <div>{userContent}</div>; // ❌ Dangerous: Don't use dangerouslySetInnerHTML unless necessary // return <div dangerouslySetInnerHTML={{ __html: userContent }} />;}Vue Example:
vue
<!-- ✅ Secure Code --><template> <div> {{ userContent }} <!-- Auto-escaped --> <!-- ❌ Dangerous: Avoid v-html with untrusted content --> <!-- <div v-html="userContent"></div> --> </div></template>Security Headers
Implementation Example
typescript
import helmet from 'helmet';app.use(helmet({ contentSecurityPolicy: { directives: { defaultSrc: ["'self'"], scriptSrc: ["'self'", "'nonce-{RANDOM}'"], styleSrc: ["'self'", "'unsafe-inline'"], imgSrc: ["'self'", "data:", "https:"], connectSrc: ["'self'"], fontSrc: ["'self'"], objectSrc: ["'none'"], mediaSrc: ["'self'"], frameSrc: ["'none'"], }, }, xssFilter: true, noSniff: true, referrerPolicy: { policy: 'same-origin' },}));Testing for XSS Vulnerabilities
Automated Testing Example
typescript
describe('XSS Prevention Tests', () => { const xssPayloads = [ '<script>alert("xss")</script>', 'javascript:alert("xss")', '<img src="x" onerror="alert('xss')">', '<svg/onload=alert("xss")>', ]; test.each(xssPayloads)('should sanitize XSS payload: %s', async (payload) => { const response = await request(app) .post('/api/comments') .send({ content: payload }); expect(response.status).toBe(200); const savedComment = await db.comments.findLatest(); expect(savedComment.content).not.toContain(payload); });});Best Practices Checklist
- ✅ Validate and sanitize all user input
- ✅ Implement proper output encoding
- ✅ Use Content Security Policy
- ✅ Enable security headers
- ✅ Use framework-provided protections
- ✅ Regularly update dependencies
- ✅ Implement automated security testing
- ✅ Conduct regular security audits
Conclusion
XSS prevention requires a multi-layered approach combining input validation, output encoding, and proper security headers. Always stay updated with the latest security best practices and regularly audit your application's security measures.
Created with WebInk - Demonstrating security documentation capabilities