OWASP Top 10 2025: Complete Guide to Web Application Security Risks
Introduction
The OWASP Top 10 is the definitive guide to the most critical web application security risks. Updated periodically, it represents the consensus of security experts worldwide on the most pressing threats facing organizations today.
This comprehensive guide covers each vulnerability in the OWASP Top 10 2025, explaining what it is, how attackers exploit it, and most importantly—how to prevent it.
Understanding OWASP
The Open Web Application Security Project (OWASP) is a nonprofit foundation that works to improve software security. Their Top 10 list is widely recognized as the benchmark for web application security and is referenced by organizations worldwide including:
- PCI DSS compliance requirements
- ISO 27001 controls
- SOC 2 audit requirements
- NIST cybersecurity framework
OWASP Top 10 2025: The Complete List
1. A01:2025 - Broken Access Control
Description: Access control enforces policy such that users cannot act outside of their intended permissions. Failures typically lead to unauthorized information disclosure, modification, or destruction of all data.
Common Vulnerabilities:
- Violation of the principle of least privilege
- Bypassing access control checks by modifying the URL
- Permitting viewing or editing someone else's account
- Accessing API with missing access controls for POST, PUT, and DELETE
- Elevation of privilege
Prevention:
// BAD: No access control check
app.get('/api/user/:id', (req, res) => {
const user = db.getUser(req.params.id);
res.json(user);
});
// GOOD: Proper authorization check
app.get('/api/user/:id', authenticateToken, (req, res) => {
const requestedUserId = req.params.id;
const currentUserId = req.user.id;
// Check if user can access this resource
if (!await authorizationService.canAccess(currentUserId, requestedUserId)) {
return res.status(403).json({ error: 'Access denied' });
}
const user = db.getUser(requestedUserId);
res.json(user);
});
Additional Measures:
- Deny by default except for public resources
- Implement access control mechanisms once and reuse
- Log access control failures and alert administrators
- Rate limit API access to minimize automated attacks
2. A02:2025 - Cryptographic Failures
Description: The first thing is to determine the protection needs of data in transit and at rest. For example, passwords, credit card numbers, health records, personal information, and business secrets require extra protection.
Common Vulnerabilities:
- Default crypto in use (MD5, SHA1)
- No encryption of sensitive data
- Weak or outdated cryptographic algorithms
- Missing encryption for data in transit
- Proper key management not implemented
Prevention:
// Use strong encryption algorithms
const crypto = require('crypto');
// Good: AES-256-GCM for encryption at rest
function encrypt(plaintext, key) {
const iv = crypto.randomBytes(12);
const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
let encrypted = cipher.update(plaintext, 'utf8', 'hex');
encrypted += cipher.final('hex');
const authTag = cipher.getAuthTag();
return {
iv: iv.toString('hex'),
encrypted,
authTag: authTag.toString('hex')
};
}
// Use TLS 1.3 for data in transit
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('private-key.pem'),
cert: fs.readFileSync('certificate.pem'),
minVersion: 'TLSv1.2',
ciphers: 'ECDHE-RSA-AES128-GCM-SHA256'
};
Additional Measures:
- Classify data processed, stored, or transmitted by an application
- Encrypt all sensitive data at rest
- Use proper key management
- Disable caching for sensitive responses
- Use strong adaptive and salted hashing for passwords
3. A03:2025 - Injection
Description: An application is vulnerable to attack when:
- User data is not validated, filtered, or sanitized
- Dynamic queries or non-parameterized calls are used
- Hostile data is used within ORM search parameters
- Hostile data is directly used or concatenated
Common Vulnerabilities:
- SQL Injection
- NoSQL Injection
- OS Command Injection
- LDAP Injection
- XPath Injection
Prevention:
// BAD: Vulnerable to SQL injection
app.get('/api/users', (req, res) => {
const query = `SELECT * FROM users WHERE name = '${req.query.name}'`;
db.query(query);
});
// GOOD: Parameterized queries prevent SQL injection
app.get('/api/users', (req, res) => {
const query = 'SELECT * FROM users WHERE name = ?';
db.query(query, [req.query.name]);
});
// GOOD: Using an ORM
const user = await User.findOne({
where: {
name: req.query.name
}
});
Additional Measures:
- Use LIMIT and other SQL controls to prevent mass disclosure
- Use stored procedures to abstract database access
- Validate, filter, and sanitize user input
- Use LIMIT to prevent SQL injection from causing mass disclosure
4. A04:2025 - Insecure Design
Description: Insecure design is a broad category representing different weaknesses, expressed as "missing or ineffective control design." There is no such thing as a secure default.
Common Vulnerabilities:
- Missing or ineffective authentication
- Missing or ineffective authorization
- Lack of input validation
- Improper error handling
- Security misconfiguration
Prevention:
// Implement proper rate limiting
const rateLimit = require('express-rate-limit');
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5, // limit each IP to 5 login attempts per window
message: { error: 'Too many login attempts, please try again later' },
validate: { xForwardedForHeader: false }
});
app.post('/auth/login', authLimiter, authController.login);
// Implement proper session management
const session = require('express-session');
app.use(session({
secret: process.env.SESSION_SECRET,
name: 'sessionId',
resave: false,
saveUninitialized: false,
cookie: {
secure: true, // use HTTPS only
httpOnly: true,
sameSite: 'strict',
maxAge: 3600000 // 1 hour
}
}));
Additional Measures:
- Use threat modeling for critical authentication, access control, and business logic flows
- Use secure design pattern libraries
- Implement proper separation of tenants
- Limit resource consumption per user
5. A05:2025 - Security Misconfiguration
Description: The application might be vulnerable if it is:
- Missing security hardening across any part of the application stack
- Using default credentials
- Having unnecessary features installed or enabled
- Using overly verbose error messages
Common Vulnerabilities:
- Missing security hardening
- Using default credentials
- Unnecessary features enabled
- Error handling reveals stack traces
- Upgraded systems have insecure old functionality
Prevention:
// Configure security headers with Helmet
const helmet = require('helmet');
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:", "https:"],
connectSrc: ["'self'"],
fontSrc: ["'self'"],
objectSrc: ["'none'"],
mediaSrc: ["'self'"],
frameSrc: ["'none'"]
}
},
hsts: {
maxAge: 31536000,
includeSubDomains: true,
preload: true
},
noSniff: true,
xssFilter: true,
referrerPolicy: { policy: 'strict-origin-when-cross-origin' }
}));
// Don't expose stack traces in production
app.use((err, req, res, next) => {
if (process.env.NODE_ENV === 'production') {
console.error(err);
return res.status(500).json({
error: 'Internal Server Error',
message: 'An unexpected error occurred'
});
}
res.status(500).json({
error: err.message,
stack: err.stack
});
});
Additional Measures:
- Repeatable hardening process makes deployment faster
- Minimal platform without unnecessary features
- Review and update configurations per OWASP Secure Configuration Guide
- Segmented application architecture provides effective security
6. A06:2025 - Vulnerable and Outdated Components
Description: You are likely vulnerable if:
- You do not know all versions of your components
- Software is unsupported
- You do not scan for vulnerabilities regularly
- You do not fix or upgrade the platform, frameworks, and dependencies in time
- You do not test compatibility of updates
Prevention:
{
"scripts": {
"audit": "npm audit",
"audit:fix": "npm audit fix"
},
"devDependencies": {
"npm-check-updates": "^16.0.0"
}
}
# Run security audit
npm audit
# Check for outdated packages
npx npm-check-updates
# Update all dependencies
npx npm-check-updates -u
npm install
Additional Measures:
- Remove unnecessary dependencies
- Continuously inventory versions of components
- Monitor for CVEs affecting your components
- Only obtain components from official sources
7. A07:2025 - Identification and Authentication Failures
Description: Confirmation of the user's identity, authentication, and session management is critical to protect against authentication-related attacks.
Common Vulnerabilities:
- Permitted weak passwords
- Session IDs exposed in the URL
- Session IDs not rotated after successful login
- Credentials stored in plain text
Prevention:
// Implement proper password validation
const passwordValidator = (password) => {
const minLength = 12;
const hasUpperCase = /[A-Z]/.test(password);
const hasLowerCase = /[a-z]/.test(password);
const hasNumbers = /\d/.test(password);
const hasSpecialChar = /[!@#$%^&*]/.test(password);
if (password.length < minLength) return 'Password must be at least 12 characters';
if (!hasUpperCase || !hasLowerCase) return 'Password must contain both uppercase and lowercase';
if (!hasNumbers) return 'Password must contain a number';
if (!hasSpecialChar) return 'Password must contain a special character';
return null; // valid
};
// Use bcrypt for password hashing
const bcrypt = require('bcrypt');
async function hashPassword(password) {
const saltRounds = 12;
return await bcrypt.hash(password, saltRounds);
}
async function verifyPassword(password, hash) {
return await bcrypt.compare(password, hash);
}
// Implement account lockout
let loginAttempts = new Map();
app.post('/auth/login', async (req, res) => {
const email = req.body.email;
const attempts = loginAttempts.get(email) || 0;
if (attempts >= 5) {
return res.status(429).json({
error: 'Account locked due to too many failed attempts'
});
}
const user = await authenticate(email, req.body.password);
if (!user) {
loginAttempts.set(email, attempts + 1);
return res.status(401).json({ error: 'Invalid credentials' });
}
loginAttempts.set(email, 0);
// Issue new session
});
Additional Measures:
- Implement multi-factor authentication
- Do not deploy with any default credentials
- Implement weak password checks
- Harden account recovery
8. A08:2025 - Software and Data Integrity Failures
Description: Software and data integrity failures relate to code and infrastructure that does not protect against integrity violations.
Common Vulnerabilities:
- Deserialization of untrusted data
- CI/CD pipeline lacks verification
- Unverified updates or patches
- Insecure deserialization
Prevention:
// Validate and sanitize deserialized data
const Ajv = require('ajv');
const ajv = new Ajv();
const userSchema = {
type: 'object',
properties: {
name: { type: 'string', maxLength: 100 },
email: { type: 'string', format: 'email' },
age: { type: 'integer', minimum: 0 }
},
required: ['name', 'email'],
additionalProperties: false
};
function validateInput(data) {
const validate = ajv.compile(userSchema);
if (!validate(data)) {
throw new Error('Invalid input: ' + validate.errors);
}
return data;
}
// Verify integrity of dependencies
// Use npm audit and lockfiles
Additional Measures:
- Use digital signatures for software and data
- Verify NPM or Maven dependencies
- Review code and configuration changes
- Ensure CI/CD pipeline has proper access controls
9. A09:2025 - Security Logging and Monitoring Failures
Description: Insufficient logging, detection, monitoring, and active response occurs any time:
- Auditable events are not logged
- Warnings and errors generate no log messages
- Logs are not monitored for suspicious activity
- Application cannot detect, escalate, or alert for active attacks
Prevention:
const winston = require('winston');
const logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
transports: [
new winston.transports.File({ filename: 'security.log' }),
new winston.transports.Console()
]
});
// Log authentication events
app.post('/auth/login', (req, res) => {
logger.info({
type: 'authentication',
method: 'login',
email: req.body.email,
ip: req.ip,
userAgent: req.headers['user-agent'],
success: false,
timestamp: new Date().toISOString()
});
});
// Log access control violations
app.use((req, res, next) => {
// Check for unauthorized access attempts
logger.warn({
type: 'access_violation',
path: req.path,
method: req.method,
ip: req.ip,
timestamp: new Date().toISOString()
});
next();
});
Additional Measures:
- Ensure logs contain sufficient context
- Use centralized log management
- Establish alerting thresholds and escalation procedures
- Implement intrusion detection systems
10. A10:2025 - Server-Side Request Forgery (SSRF)
Description: SSRF flaws occur whenever a web application fetches a remote resource without validating the user-supplied URL.
Common Vulnerabilities:
- Fetching data from URLs
- Importing data from URLs
- Webhooks
- URL processing
- Document rendering
Prevention:
// Validate and sanitize URLs
const { URL } = require('url');
const dns = require('dns').promises;
const BLOCKED_HOSTS = [
'localhost',
'127.0.0.1',
'0.0.0.0',
'metadata.google.internal'
];
const BLOCKED_PROTOCOLS = ['file:', 'ftp:', 'gopher:'];
async function isUrlSafe(urlString) {
try {
const url = new URL(urlString);
// Check for blocked protocols
if (BLOCKED_PROTOCOLS.includes(url.protocol)) {
return false;
}
// Check for blocked hosts
if (BLOCKED_HOSTS.includes(url.hostname)) {
return false;
}
// Resolve hostname to IP
const addresses = await dns.resolve4(url.hostname);
// Check for private IPs
const privateRanges = [
'10.',
'172.16.',
'192.168.',
'127.'
];
for (const addr of addresses) {
if (privateRanges.some(range => addr.startsWith(range))) {
return false;
}
}
return true;
} catch (error) {
return false;
}
}
app.get('/fetch-url', async (req, res) => {
const url = req.query.url;
if (!await isUrlSafe(url)) {
return res.status(400).json({ error: 'URL not allowed' });
}
// Safe to fetch
const response = await fetch(url);
const data = await response.text();
res.json({ data });
});
Additional Measures:
- Enforce "deny by default" firewall policies
- Disable HTTP redirections
- Ensure sanity of URL supplied by client
- Do not send raw responses to clients
Quick Reference: OWASP Top 10 Checklist
Use this checklist to assess your application's security:
Access Control
- [ ] Implement role-based access control (RBAC)
- [ ] Deny by default
- [ ] Log all access control failures
- [ ] Rate limit API access
Cryptography
- [ ] Encrypt sensitive data at rest
- [ ] Use TLS for data in transit
- [ ] Use strong algorithms (AES-256, SHA-256)
- [ ] Manage keys securely
Injection
- [ ] Use parameterized queries
- [ ] Validate and sanitize input
- [ ] Use LIMIT in SQL queries
- [ ] Avoid dynamic queries
Security Design
- [ ] Use threat modeling
- [ ] Implement secure defaults
- [ ] Apply defense in depth
- [ ] Use secure design patterns
Security Configuration
- [ ] Configure security headers
- [ ] Disable default credentials
- [ ] Remove unnecessary features
- [ ] Use error handling
Components
- [ ] Keep dependencies updated
- [ ] Scan for vulnerabilities
- [ ] Remove unused dependencies
- [ ] Monitor CVE feeds
Authentication
- [ ] Use multi-factor authentication
- [ ] Implement account lockout
- [ ] Use strong password policies
- [ ] Hash passwords with bcrypt/argon2
Integrity
- [ ] Use digital signatures
- [ ] Verify dependencies
- [ ] Secure CI/CD pipeline
- [ ] Validate deserialized data
Logging
- [ ] Log authentication events
- [ ] Log access control failures
- [ ] Use centralized logging
- [ ] Set up alerting
SSRF
- [ ] Validate URLs
- [ ] Block internal services
- [ ] Disable HTTP redirects
- [ ] Use allowlists
Conclusion
Understanding and addressing the OWASP Top 10 is essential for any organization developing or maintaining web applications. These vulnerabilities represent the most common and critical risks that attackers target.
Key takeaways:
- Defense in depth - Multiple layers of security provide better protection
- Secure by default - Start with secure configurations
- Continuous assessment - Regularly test and update your security
- Stay informed - OWASP updates their list as threats evolve
Remember: Security is not a one-time effort but an ongoing process. Regularly review your applications against these risks and keep your security measures up to date.
Need help securing your applications? Contact DevSecure for a comprehensive security assessment and penetration testing services. Our experts can help you identify and remediate these vulnerabilities before attackers exploit them.
Need help securing your systems?
Our expert security team can help you identify and fix vulnerabilities before attackers exploit them.
DevSecure Team
Security expert at DevSecure. Passionate about cybersecurity and helping organizations protect their digital assets.