Back to Blog
Tutorial2025-01-10

JavaScript Security Best Practices

Protect your JavaScript applications from XSS, CSRF, injection attacks, and other common security vulnerabilities.

Cross-Site Scripting (XSS)

XSS is the most common web vulnerability. Never trust user input.

Preventing XSS

``javascript // BAD: Direct HTML insertion element.innerHTML = userInput; // XSS vulnerability!

// GOOD: Use textContent for plain text element.textContent = userInput;

// GOOD: Sanitize HTML if you must render it import DOMPurify from 'dompurify'; element.innerHTML = DOMPurify.sanitize(userInput);

// GOOD: Use template literals with encoding function escapeHtml(str) { const div = document.createElement('div'); div.textContent = str; return div.innerHTML; } `

Content Security Policy

`html `

Avoiding eval() and Similar

`javascript // BAD: Never use these with user input eval(userInput); new Function(userInput); setTimeout(userInput, 1000);

// GOOD: Use JSON.parse for data const data = JSON.parse(jsonString);

// GOOD: Use safe alternatives const fn = () => { /* predefined logic */ }; setTimeout(fn, 1000); `

Secure Data Handling

`javascript // Validate and sanitize all input function validateEmail(email) { const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return regex.test(email) && email.length <= 254; }

// Don't store sensitive data in localStorage // BAD localStorage.setItem('token', authToken); // Accessible to XSS

// BETTER: Use httpOnly cookies (server-side) // Set-Cookie: token=xxx; HttpOnly; Secure; SameSite=Strict `

API Security

`javascript // Always validate on the server side too // Use HTTPS for all API calls // Implement rate limiting // Use CORS properly

const response = await fetch('/api/data', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': csrfToken, // CSRF protection }, credentials: 'same-origin', body: JSON.stringify(data) }); `

Dependency Security

`bash # Audit your dependencies regularly npm audit npm audit fix

# Use lockfiles # Keep dependencies updated npx npm-check-updates `

Prototype Pollution Prevention

`javascript // BAD: Deep merge without protection function merge(target, source) { for (const key in source) { if (typeof source[key] === 'object') { merge(target[key], source[key]); // Prototype pollution! } else { target[key] = source[key]; } } }

// GOOD: Check for dangerous keys function safeMerge(target, source) { for (const key of Object.keys(source)) { if (key === '__proto__' || key === 'constructor' || key === 'prototype') { continue; // Skip dangerous keys } if (typeof source[key] === 'object' && source[key] !== null) { target[key] = safeMerge(target[key] || {}, source[key]); } else { target[key] = source[key]; } } return target; } `

Summary

Security is not optional. Sanitize all user input, avoid eval()`, use Content Security Policy, keep dependencies updated, validate on both client and server, and use HTTPS everywhere.