OWASP Top 10:2025
When NOT to Use This Skill
- OWASP Top 10:2021 - Use
owasp skill for 2021 version
- Detailed secrets management - Use
secrets-management skill
- Detailed supply chain security - Use
supply-chain skill for in-depth dependency management
- License compliance - Use
license-compliance skill
Deep Knowledge: Use mcp__documentation__fetch_docs with technology: owasp for comprehensive documentation.
Quick Reference
| Rank |
Category |
Prevention |
| A01 |
Broken Access Control |
Authorization checks, deny by default |
| A02 |
Security Misconfiguration |
Hardening, security headers, no defaults |
| A03 |
Supply Chain Failures |
Dependency audits, lockfiles, SBOMs |
| A04 |
Cryptographic Failures |
Strong algorithms, proper key management |
| A05 |
Injection |
Parameterized queries, input validation |
| A06 |
Insecure Design |
Threat modeling, secure patterns |
| A07 |
Authentication Failures |
MFA, rate limiting, secure sessions |
| A08 |
Integrity Failures |
Signed updates, safe deserialization |
| A09 |
Logging Failures |
Audit logs, alerting, monitoring |
| A10 |
Exception Handling |
Graceful errors, no info leakage |
A01: Broken Access Control
// Always verify ownership
if (resource.userId !== currentUser.id) {
throw new ForbiddenException();
}
// Deny by default
const allowed = permissions.includes(requiredPermission);
if (!allowed) throw new ForbiddenException();
// Rate limit sensitive endpoints
app.use('/api/admin/*', adminRateLimiter);
A02: Security Misconfiguration
// Security headers
import helmet from 'helmet';
app.use(helmet());
// Strict CORS
app.use(cors({
origin: ['https://myapp.com'],
credentials: true
}));
// Hide errors in production
if (process.env.NODE_ENV === 'production') {
app.use((err, req, res, next) => {
res.status(500).json({ error: 'Internal error' });
});
}
A03: Supply Chain Failures (NEW in 2025)
# Audit dependencies
npm audit
pip-audit
mvn dependency-check:check
# Use lockfiles
npm ci # Instead of npm install
# Verify package integrity
npm install --ignore-scripts
npm config set ignore-scripts true
A04: Cryptographic Failures
// Strong password hashing
import { hash, verify } from 'argon2';
const hashed = await hash(password, { type: argon2id });
// Secure random
import { randomBytes, randomUUID } from 'crypto';
const token = randomBytes(32).toString('hex');
// AES-256-GCM for encryption (not CBC)
A05: Injection
// SQL - use parameterized queries
const user = await prisma.user.findUnique({ where: { id } });
await db.query('SELECT * FROM users WHERE id = $1', [id]);
// Command - use execFile, not exec
import { execFile } from 'child_process';
execFile('ls', ['-la', safeArg]);
// XSS - sanitize HTML
import DOMPurify from 'dompurify';
element.innerHTML = DOMPurify.sanitize(userInput);
A06: Insecure Design
Key practices:
- Threat modeling during design phase
- Secure design patterns (fail-safe, defense in depth)
- Security requirements in user stories
- Abuse case testing
A07: Authentication Failures
// Rate limiting
import rateLimit from 'express-rate-limit';
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 5
});
// Secure cookies
res.cookie('session', token, {
httpOnly: true,
secure: true,
sameSite: 'strict'
});
// Strong passwords (12+ chars, mixed)
A08: Integrity Failures
// Verify signatures on updates
// Use subresource integrity (SRI)
<script src="lib.js"
integrity="sha384-..."
crossorigin="anonymous">
</script>
// Safe deserialization
// Avoid: JSON.parse(untrusted)
// Use: zod/yup validation
A09: Logging & Alerting Failures
// Log security events
logger.warn({
event: 'auth_failure',
userId: attemptedId,
ip: req.ip,
timestamp: new Date().toISOString()
});
// Events to log:
// - Login success/failure
// - Password changes
// - Permission denied
// - Rate limit exceeded
A10: Exception Handling (NEW in 2025)
// Graceful error handling
try {
await riskyOperation();
} catch (error) {
logger.error({ error, context });
// Generic response to user
throw new InternalServerException('Operation failed');
}
// Never expose stack traces
// Never expose internal paths
// Never expose SQL/DB errors
Security Scanning Commands
# Dependencies
npm audit --json
snyk test
# Secrets
gitleaks detect
trufflehog git file://.
# SAST
semgrep --config=p/security-audit .
# Docker
trivy image myimage:latest
Checklist
| Risk |
Prevention |
| SQL Injection |
Parameterized queries, ORMs |
| XSS |
Escape output, CSP headers |
| CSRF |
CSRF tokens, SameSite cookies |
| Auth issues |
MFA, rate limiting, secure sessions |
| Secrets |
Environment variables, vaults |
| Supply chain |
Audit, lockfiles, SBOMs |
Anti-Patterns
| Anti-Pattern |
Why It's Bad |
Correct Approach |
| Checking permissions in frontend only |
Client-side bypass (A01) |
Always verify on backend |
| Using weak crypto (MD5, DES) |
Easily broken (A04) |
Use AES-256-GCM, argon2, SHA-256+ |
npm install in CI/CD |
Non-deterministic builds (A03) |
Use npm ci with lockfiles |
| Catching all exceptions silently |
Hides security issues (A10) |
Log errors, fail gracefully |
| Trusting user input in queries |
Injection attacks (A05) |
Always use parameterized queries |
| No session timeout |
Session hijacking (A07) |
Implement idle + absolute timeout |
Quick Troubleshooting
| Issue |
Likely Cause |
Solution |
| npm audit shows vulnerabilities |
Outdated dependencies (A03) |
Run npm audit fix or update manually |
| Login always fails after 5 attempts |
Rate limiter too strict (A07) |
Review rate limit settings |
| Secrets leaked in git history |
Committed .env file (A02) |
Use BFG to clean history, rotate secrets |
| Database queries slow/failing |
SQL injection attack (A05) |
Review logs, switch to parameterized queries |
| Users accessing others' data |
Missing authorization (A01) |
Add ownership checks in all endpoints |
| Stack traces in production |
Exception handling disabled (A10) |
Enable production error handling |
Related Skills
1---2name: owasp-top-103description: OWASP Top 10:2025 security vulnerabilities. Covers access control, injection, supply chain, cryptographic failures, and more. Use for security reviews. USE WHEN: user mentions "OWASP 2025", "Top 10", "security review", "vulnerability assessment", asks about "broken access control", "injection", "supply chain", "cryptographic failures", "exception handling" DO NOT USE FOR: general OWASP (2021) - use `owasp` instead, secrets - use `secrets-management`, dependencies - use `supply-chain`4---5# OWASP Top 10:202567## When NOT to Use This Skill8- **OWASP Top 10:2021** - Use `owasp` skill for 2021 version9- **Detailed secrets management** - Use `secrets-management` skill10- **Detailed supply chain security** - Use `supply-chain` skill for in-depth dependency management11- **License compliance** - Use `license-compliance` skill1213> **Deep Knowledge**: Use `mcp__documentation__fetch_docs` with technology: `owasp` for comprehensive documentation.1415## Quick Reference1617| Rank | Category | Prevention |18|------|----------|------------|19| A01 | Broken Access Control | Authorization checks, deny by default |20| A02 | Security Misconfiguration | Hardening, security headers, no defaults |21| A03 | Supply Chain Failures | Dependency audits, lockfiles, SBOMs |22| A04 | Cryptographic Failures | Strong algorithms, proper key management |23| A05 | Injection | Parameterized queries, input validation |24| A06 | Insecure Design | Threat modeling, secure patterns |25| A07 | Authentication Failures | MFA, rate limiting, secure sessions |26| A08 | Integrity Failures | Signed updates, safe deserialization |27| A09 | Logging Failures | Audit logs, alerting, monitoring |28| A10 | Exception Handling | Graceful errors, no info leakage |2930## A01: Broken Access Control3132```typescript33// Always verify ownership34if (resource.userId !== currentUser.id) {35 throw new ForbiddenException();36}3738// Deny by default39const allowed = permissions.includes(requiredPermission);40if (!allowed) throw new ForbiddenException();4142// Rate limit sensitive endpoints43app.use('/api/admin/*', adminRateLimiter);44```4546## A02: Security Misconfiguration4748```typescript49// Security headers50import helmet from 'helmet';51app.use(helmet());5253// Strict CORS54app.use(cors({55 origin: ['https://myapp.com'],56 credentials: true57}));5859// Hide errors in production60if (process.env.NODE_ENV === 'production') {61 app.use((err, req, res, next) => {62 res.status(500).json({ error: 'Internal error' });63 });64}65```6667## A03: Supply Chain Failures (NEW in 2025)6869```bash70# Audit dependencies71npm audit72pip-audit73mvn dependency-check:check7475# Use lockfiles76npm ci # Instead of npm install7778# Verify package integrity79npm install --ignore-scripts80npm config set ignore-scripts true81```8283## A04: Cryptographic Failures8485```typescript86// Strong password hashing87import { hash, verify } from 'argon2';88const hashed = await hash(password, { type: argon2id });8990// Secure random91import { randomBytes, randomUUID } from 'crypto';92const token = randomBytes(32).toString('hex');9394// AES-256-GCM for encryption (not CBC)95```9697## A05: Injection9899```typescript100// SQL - use parameterized queries101const user = await prisma.user.findUnique({ where: { id } });102await db.query('SELECT * FROM users WHERE id = $1', [id]);103104// Command - use execFile, not exec105import { execFile } from 'child_process';106execFile('ls', ['-la', safeArg]);107108// XSS - sanitize HTML109import DOMPurify from 'dompurify';110element.innerHTML = DOMPurify.sanitize(userInput);111```112113## A06: Insecure Design114115Key practices:116- Threat modeling during design phase117- Secure design patterns (fail-safe, defense in depth)118- Security requirements in user stories119- Abuse case testing120121## A07: Authentication Failures122123```typescript124// Rate limiting125import rateLimit from 'express-rate-limit';126const loginLimiter = rateLimit({127 windowMs: 15 * 60 * 1000,128 max: 5129});130131// Secure cookies132res.cookie('session', token, {133 httpOnly: true,134 secure: true,135 sameSite: 'strict'136});137138// Strong passwords (12+ chars, mixed)139```140141## A08: Integrity Failures142143```typescript144// Verify signatures on updates145// Use subresource integrity (SRI)146<script src="lib.js"147 integrity="sha384-..."148 crossorigin="anonymous">149</script>150151// Safe deserialization152// Avoid: JSON.parse(untrusted)153// Use: zod/yup validation154```155156## A09: Logging & Alerting Failures157158```typescript159// Log security events160logger.warn({161 event: 'auth_failure',162 userId: attemptedId,163 ip: req.ip,164 timestamp: new Date().toISOString()165});166167// Events to log:168// - Login success/failure169// - Password changes170// - Permission denied171// - Rate limit exceeded172```173174## A10: Exception Handling (NEW in 2025)175176```typescript177// Graceful error handling178try {179 await riskyOperation();180} catch (error) {181 logger.error({ error, context });182 // Generic response to user183 throw new InternalServerException('Operation failed');184}185186// Never expose stack traces187// Never expose internal paths188// Never expose SQL/DB errors189```190191## Security Scanning Commands192193```bash194# Dependencies195npm audit --json196snyk test197198# Secrets199gitleaks detect200trufflehog git file://.201202# SAST203semgrep --config=p/security-audit .204205# Docker206trivy image myimage:latest207```208209## Checklist210211| Risk | Prevention |212|------|------------|213| SQL Injection | Parameterized queries, ORMs |214| XSS | Escape output, CSP headers |215| CSRF | CSRF tokens, SameSite cookies |216| Auth issues | MFA, rate limiting, secure sessions |217| Secrets | Environment variables, vaults |218| Supply chain | Audit, lockfiles, SBOMs |219220## Anti-Patterns221222| Anti-Pattern | Why It's Bad | Correct Approach |223|--------------|--------------|------------------|224| Checking permissions in frontend only | Client-side bypass (A01) | Always verify on backend |225| Using weak crypto (MD5, DES) | Easily broken (A04) | Use AES-256-GCM, argon2, SHA-256+ |226| `npm install` in CI/CD | Non-deterministic builds (A03) | Use `npm ci` with lockfiles |227| Catching all exceptions silently | Hides security issues (A10) | Log errors, fail gracefully |228| Trusting user input in queries | Injection attacks (A05) | Always use parameterized queries |229| No session timeout | Session hijacking (A07) | Implement idle + absolute timeout |230231## Quick Troubleshooting232233| Issue | Likely Cause | Solution |234|-------|--------------|----------|235| npm audit shows vulnerabilities | Outdated dependencies (A03) | Run `npm audit fix` or update manually |236| Login always fails after 5 attempts | Rate limiter too strict (A07) | Review rate limit settings |237| Secrets leaked in git history | Committed .env file (A02) | Use BFG to clean history, rotate secrets |238| Database queries slow/failing | SQL injection attack (A05) | Review logs, switch to parameterized queries |239| Users accessing others' data | Missing authorization (A01) | Add ownership checks in all endpoints |240| Stack traces in production | Exception handling disabled (A10) | Enable production error handling |241242## Related Skills243- [Supply Chain Security](../supply-chain/SKILL.md)244- [Secrets Management](../secrets-management/SKILL.md)245- [JWT Security](../../authentication/jwt/SKILL.md)