Fixing Vulnerabilities
Practical guides and code examples for fixing common security vulnerabilities. Learn remediation techniques, prevention strategies, and best practices for secure code development.
๐๏ธ SQL Injection Prevention
๐จ NEVER DO THIS
Vulnerable Code:
// VULNERABLE - String concatenation const query = "SELECT * FROM users WHERE id = " + userId; db.query(query);
โ Prepared Statements
Node.js + MySQL:
const query = "SELECT * FROM users WHERE id = ?";
db.query(query, [userId], (err, results) => {
// Safe from SQL injection
});Python + SQLite:
cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))
results = cursor.fetchall()๐ง ORM Solutions
Prisma ORM:
const user = await prisma.user.findUnique({
where: { id: userId }
});TypeORM:
const user = await userRepository.findOne({
where: { id: userId }
});๐ก๏ธ Input Validation
Type Checking:
// Ensure userId is a number
const userId = parseInt(req.params.id);
if (isNaN(userId)) {
return res.status(400).json({ error: 'Invalid ID' });
}Sanitization:
// Remove dangerous characters const cleanInput = input.replace(/[<>'"&]/g, ''); // Or use a library like validator.js const sanitized = validator.escape(dirtyInput);
๐ Cross-Site Scripting (XSS) Protection
๐จ DANGEROUS PATTERNS
// VULNERABLE - Direct HTML insertion const html = "<div>" + userInput + "</div>"; element.innerHTML = html;
โ Output Encoding
HTML Context:
// Use textContent instead of innerHTML
element.textContent = userInput;
// Or escape HTML entities
const safeHTML = escapeHtml(userInput);
element.innerHTML = `<div>${safeHTML}</div>`;๐ง Content Security Policy
HTTP Headers:
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';
๐ก๏ธ Framework Protection
React:
// React automatically escapes JSX
const element = <div>{userInput}</div>;
// For dangerouslySetInnerHTML, sanitize first
const sanitizedHTML = DOMPurify.sanitize(dirtyHTML);
<div dangerouslySetInnerHTML={{__html: sanitizedHTML}} />๐งน Input Sanitization Libraries
DOMPurify
HTML sanitization
validator.js
Input validation
xss
XSS filtering
sanitize-html
HTML cleaner
๐ Authentication & Authorization Fixes
Session Management
Secure Session Config
app.use(session({
name: 'sessionId', // Don't use default
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
cookie: {
secure: true, // HTTPS only
httpOnly: true, // Prevent XSS
maxAge: 30 * 60 * 1000 // 30 minutes
}
}));JWT Best Practices
const token = jwt.sign(
{ userId, role },
process.env.JWT_SECRET,
{
expiresIn: '1h',
issuer: 'your-app',
audience: 'your-users'
}
);Password Security
Strong Hashing
const bcrypt = require('bcrypt');
const saltRounds = 12;
const hash = await bcrypt.hash(password, saltRounds);
const isValid = await bcrypt.compare(password, hash);Password Policies
const isStrong = password.length >= 12 && /[A-Z]/.test(password) && /[a-z]/.test(password) && /[0-9]/.test(password) && /[^A-Za-z0-9]/.test(password);
๐ Authorization Patterns
Role-Based Access:
const authorize = (roles) => (req, res, next) => {
if (!roles.includes(req.user.role)) {
return res.status(403).json({ error: 'Access denied' });
}
next();
};
// Usage
app.get('/admin', authorize(['admin']), handler);Resource-Based Access:
const canAccess = (user, resource, action) => {
// Check ownership or permissions
return resource.ownerId === user.id ||
user.permissions.includes(action);
};
if (!canAccess(user, post, 'edit')) {
throw new ForbiddenError();
}๐ File Upload Security
File Type Validation
MIME Type Checking
const allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
const fileType = await fileTypeFromBuffer(buffer);
if (!allowedTypes.includes(fileType.mime)) {
throw new Error('Invalid file type');
}Extension Validation
const allowedExts = ['.jpg', '.jpeg', '.png', '.gif'];
const ext = path.extname(filename).toLowerCase();
if (!allowedExts.includes(ext)) {
throw new Error('Invalid file extension');
}Security Measures
Random Filenames
const crypto = require('crypto');
const randomName = crypto.randomBytes(16).toString('hex');
const extension = path.extname(originalName);
const safeName = `${randomName}${extension}`;Size Limits
const MAX_SIZE = 5 * 1024 * 1024; // 5MB
if (file.size > MAX_SIZE) {
throw new Error('File too large');
}๐จ Directory Traversal Prevention
// DANGEROUS - Allows directory traversal const filePath = path.join(uploadDir, req.body.filename); // SAFE - Use basename and validate const filename = path.basename(req.body.filename); const safePath = path.join(uploadDir, filename); // Even safer - Generate your own filename const safeName = generateSafeFilename(); const safePath = path.join(uploadDir, safeName);
๐ฆ Dependency Vulnerability Management
Regular Updates
โข Run
npm audit weeklyโข Update dependencies monthly
โข Test after updates
โข Use
npm audit fixAutomated Tools
โข Dependabot (GitHub)
โข Snyk
โข npm audit
โข OWASP Dependency Check
Lock Files
โข Commit package-lock.json
โข Use exact versions
โข Regular integrity checks
โข CI/CD validation
๐ Update Strategy
Patch Updates (Safe):
- โข Bug fixes only
- โข No breaking changes
- โข Automated updates OK
- โข Low testing required
Major Updates (Careful):
- โข Breaking changes possible
- โข Manual review required
- โข Full test suite needed
- โข Deployment planning
Quick Fixes
SQL Injection:
Use prepared statements
XSS:
Escape output, CSP headers
Auth:
Strong passwords, MFA
Testing Fixes
โข Unit tests for validation
โข Integration tests for auth
โข Security regression tests
โข Penetration testing
โข Code review checklist
Prevention Tools
๐ก๏ธ ESLint Security
๐ SAST Scanners
๐ Dependency Checkers
๐จ Runtime Protection
