π OWASP Top 10 (2026)
- Broken Access Control
- Cryptographic Failures
- Injection (SQL, XSS)
- Insecure Design
- Security Misconfiguration
- Vulnerable Components
- Authentication Failures
- Data Integrity Failures
- Logging & Monitoring Failures
- Server-Side Request Forgery (SSRF)
β οΈ Common Vulnerabilities
1. Cross-Site Scripting (XSS)
Injecting malicious scripts into web pages viewed by other users.
// β Vulnerable Code
<div innerHTML={userInput}></div>
// β
Safe Code
import DOMPurify from 'dompurify'
<div innerHTML={DOMPurify.sanitize(userInput)}></div>
// React automatically escapes
<div>{userInput}</div>
// Prevention:
β’ Escape user input
β’ Use Content Security Policy (CSP)
β’ Sanitize HTML
β’ Validate input2. SQL Injection
// β Vulnerable
const query = `SELECT * FROM users WHERE id = ${userId}`
// β
Safe - Parameterized Query
const query = 'SELECT * FROM users WHERE id = ?'
db.query(query, [userId])
// β
Safe - ORM
const user = await User.findByPk(userId)
// Prevention:
β’ Use parameterized queries
β’ Use ORMs (Sequelize, Prisma)
β’ Validate input
β’ Least privilege database access3. Cross-Site Request Forgery (CSRF)
// β
CSRF Token
// Backend
app.use(csrf())
app.get('/form', (req, res) => {
res.render('form', { csrfToken: req.csrfToken() })
})
// Frontend
<form method="POST">
<input type="hidden" name="_csrf" value={csrfToken} />
<button type="submit">Submit</button>
</form>
// Prevention:
β’ CSRF tokens
β’ SameSite cookies
β’ Verify Origin/Referer headers
β’ Double submit cookiesπ Authentication & Authorization
Password Security
// β
Hash Passwords with bcrypt
const bcrypt = require('bcrypt')
// Register
const hashedPassword = await bcrypt.hash(password, 10)
await User.create({ email, password: hashedPassword })
// Login
const user = await User.findOne({ where: { email } })
const isValid = await bcrypt.compare(password, user.password)
// Best Practices:
β’ Never store plain text passwords
β’ Use bcrypt, argon2, or scrypt
β’ Salt rounds: 10-12
β’ Enforce strong password policy
β’ Implement rate limiting
β’ Use 2FA/MFAJWT Security
const jwt = require('jsonwebtoken')
// β
Generate Token
const token = jwt.sign(
{ userId: user.id, role: user.role },
process.env.JWT_SECRET,
{ expiresIn: '1h' }
)
// β
Verify Token
const decoded = jwt.verify(token, process.env.JWT_SECRET)
// Best Practices:
β’ Use strong secret (256-bit)
β’ Short expiration time
β’ Refresh tokens for long sessions
β’ Store in httpOnly cookies
β’ Validate on every request
β’ Implement token blacklist for logoutπ HTTPS & TLS
Why HTTPS?
- Encryption: Data encrypted in transit
- Authentication: Verify server identity
- Integrity: Detect tampering
- SEO: Google ranking factor
- Trust: Browser security indicators
// Free SSL Certificates
β’ Let's Encrypt (certbot)
β’ Cloudflare
β’ AWS Certificate Manager
β’ Vercel/Netlify (automatic)
// Security Headers
app.use((req, res, next) => {
res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains')
res.setHeader('X-Content-Type-Options', 'nosniff')
res.setHeader('X-Frame-Options', 'DENY')
res.setHeader('X-XSS-Protection', '1; mode=block')
next()
})π‘οΈ Content Security Policy (CSP)
// CSP Header
Content-Security-Policy:
default-src 'self';
script-src 'self' 'unsafe-inline' https://cdn.example.com;
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
font-src 'self' https://fonts.gstatic.com;
connect-src 'self' https://api.example.com;
frame-ancestors 'none';
// Next.js Example
// next.config.js
const securityHeaders = [
{
key: 'Content-Security-Policy',
value: "default-src 'self'; script-src 'self' 'unsafe-eval' 'unsafe-inline';"
}
]
module.exports = {
async headers() {
return [{ source: '/:path*', headers: securityHeaders }]
}
}π Input Validation
// β
Validate with Zod
import { z } from 'zod'
const userSchema = z.object({
email: z.string().email(),
password: z.string().min(8).max(100),
age: z.number().min(18).max(120)
})
try {
const validData = userSchema.parse(req.body)
} catch (error) {
return res.status(400).json({ error: error.errors })
}
// β
Sanitize Input
import validator from 'validator'
const email = validator.normalizeEmail(req.body.email)
const name = validator.escape(req.body.name)
// Rules:
β’ Validate on client AND server
β’ Whitelist, don't blacklist
β’ Sanitize before storage
β’ Validate data types
β’ Check length limitsπ¨ Rate Limiting
// Express Rate Limit
const rateLimit = require('express-rate-limit')
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // Limit each IP to 100 requests per windowMs
message: 'Too many requests, please try again later.'
})
app.use('/api/', limiter)
// Login Rate Limit (stricter)
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 5,
skipSuccessfulRequests: true
})
app.post('/api/login', loginLimiter, loginHandler)
// Benefits:
β’ Prevent brute force attacks
β’ Prevent DDoS
β’ Reduce server load
β’ Fair resource usageπ Security Checklist
- β HTTPS enabled everywhere
- β Security headers configured
- β Input validation (client & server)
- β Output encoding/escaping
- β Parameterized queries (no SQL injection)
- β CSRF protection
- β XSS protection (CSP)
- β Password hashing (bcrypt)
- β JWT with short expiration
- β Rate limiting
- β Dependencies updated
- β Error handling (no sensitive info)
- β Logging & monitoring
- β Regular security audits
π― Conclusion
Web security is not optionalβit's essential. Implement defense in depth: multiple layers of security. Stay updated with OWASP guidelines, use security tools, and make security part of your development process from day one.
π Generate Secure Passwords
Need strong passwords? Use our Password Generator to create secure, random passwords.
Generate Password β