Web Security Essentials
Security isn't optional. Every developer must understand these vulnerabilities and defenses.
Cross-Site Scripting (XSS)
Attackers inject malicious scripts:
// Vulnerable
element.innerHTML = userInput;
// Safe - escape HTML
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// Or use textContent
element.textContent = userInput;
Prevention
- Escape user input before rendering
- Use Content Security Policy (CSP)
- Use frameworks that auto-escape (React, Vue)
SQL Injection
Never concatenate user input into queries:
// Vulnerable
const query = `SELECT * FROM users WHERE id = ${userId}`;
// Safe - parameterized queries
const query = 'SELECT * FROM users WHERE id = ?';
db.query(query, [userId]);
Cross-Site Request Forgery (CSRF)
Attackers trick users into unwanted actions:
Prevention
// Generate CSRF token
const csrfToken = crypto.randomBytes(32).toString('hex');
// Include in forms
<input type="hidden" name="_csrf" value="${csrfToken}">
// Validate on server
if (req.body._csrf !== session.csrfToken) {
return res.status(403).send('Invalid CSRF token');
}
Security Headers
Add these headers:
// Using Helmet.js
const helmet = require('helmet');
app.use(helmet());
// Or manually
app.use((req, res, next) => {
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('X-XSS-Protection', '1; mode=block');
res.setHeader('Strict-Transport-Security', 'max-age=31536000');
next();
});
Password Security
Hash passwords properly:
const bcrypt = require('bcrypt');
// Hashing
const hash = await bcrypt.hash(password, 12);
// Verifying
const match = await bcrypt.compare(password, hash);
Environment Variables
Never commit secrets:
# .env (add to .gitignore)
DATABASE_URL=postgres://...
JWT_SECRET=your-secret-key
API_KEY=your-api-key
HTTPS Everywhere
Force secure connections:
app.use((req, res, next) => {
if (!req.secure && req.get('X-Forwarded-Proto') !== 'https') {
return res.redirect(`https://${req.get('Host')}${req.url}`);
}
next();
});
Conclusion
Security requires constant vigilance. Make these practices part of your development workflow.