OWASP Security Best Practices
Apply these security standards when writing or reviewing code.
For deeper material, load on demand:
- references/language-security-quirks.md: language-specific pitfalls and unsafe/safe patterns for 20 languages (JS/TS, Python, Java, C#, PHP, Go, Ruby, Rust, Swift, Kotlin, C/C++, Scala, R, Perl, Bash, Lua, Elixir, Dart, PowerShell, SQL). Read it when reviewing code in a specific language.
- references/llm-agentic-security.md: OWASP Top 10 for LLM Applications (2025) and Agentic AI security (2026), with checklists and code patterns. Read it when the code calls an LLM, builds a RAG pipeline, or wires up an AI agent with tools.
Quick Reference: OWASP Top 10:2025
| # |
Vulnerability |
Key Prevention |
| A01 |
Broken Access Control |
Deny by default, enforce server-side, verify ownership |
| A02 |
Security Misconfiguration |
Harden configs, disable defaults, minimize features |
| A03 |
Supply Chain Failures |
Lock versions, verify integrity, audit dependencies |
| A04 |
Cryptographic Failures |
TLS 1.2+, AES-256-GCM, Argon2/bcrypt for passwords |
| A05 |
Injection |
Parameterized queries, input validation, safe APIs |
| A06 |
Insecure Design |
Threat model, rate limit, design security controls |
| A07 |
Auth Failures |
MFA, check breached passwords, secure sessions |
| A08 |
Integrity Failures |
Sign packages, SRI for CDN, safe serialization |
| A09 |
Logging Failures |
Log security events, structured format, alerting |
| A10 |
Exception Handling |
Fail-closed, hide internals, log with context |
Security Code Review Checklist
When reviewing code, check for these issues:
Input Handling
Authentication & Sessions
Access Control
Data Protection
Error Handling
Secure Code Patterns
SQL Injection Prevention
# UNSAFE
cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")
# SAFE
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
Command Injection Prevention
# UNSAFE
os.system(f"convert {filename} output.png")
# SAFE
subprocess.run(["convert", filename, "output.png"], shell=False)
Password Storage
# UNSAFE
hashlib.md5(password.encode()).hexdigest()
# SAFE
from argon2 import PasswordHasher
PasswordHasher().hash(password)
Access Control
# UNSAFE - No authorization check
@app.route('/api/user/<user_id>')
def get_user(user_id):
return db.get_user(user_id)
# SAFE - Authorization enforced
@app.route('/api/user/<user_id>')
@login_required
def get_user(user_id):
if current_user.id != user_id and not current_user.is_admin:
abort(403)
return db.get_user(user_id)
Error Handling
# UNSAFE - Exposes internals
@app.errorhandler(Exception)
def handle_error(e):
return str(e), 500
# SAFE - Fail-closed, log context
@app.errorhandler(Exception)
def handle_error(e):
error_id = uuid.uuid4()
logger.exception(f"Error {error_id}: {e}")
return {"error": "An error occurred", "id": str(error_id)}, 500
Fail-Closed Pattern
# UNSAFE - Fail-open
def check_permission(user, resource):
try:
return auth_service.check(user, resource)
except Exception:
return True # DANGEROUS!
# SAFE - Fail-closed
def check_permission(user, resource):
try:
return auth_service.check(user, resource)
except Exception as e:
logger.error(f"Auth check failed: {e}")
return False # Deny on error
ASVS 5.0 Key Requirements
Level 1 (All Applications)
- Passwords minimum 12 characters
- Check against breached password lists
- Rate limiting on authentication
- Session tokens 128+ bits entropy
- HTTPS everywhere
Level 2 (Sensitive Data)
- All L1 requirements plus:
- MFA for sensitive operations
- Cryptographic key management
- Comprehensive security logging
- Input validation on all parameters
Level 3 (Critical Systems)
- All L1/L2 requirements plus:
- Hardware security modules for keys
- Threat modeling documentation
- Advanced monitoring and alerting
- Penetration testing validation
Deep Security Analysis Mindset
When reviewing any language, think like a senior security researcher:
- Memory Model: How does the language handle memory? Managed vs manual? GC pauses exploitable?
- Type System: Weak typing = type confusion attacks. Look for coercion exploits.
- Serialization: Every language has a native-object deserializer. All are dangerous with untrusted input.
- Concurrency: Race conditions, TOCTOU, atomicity failures specific to the threading model.
- FFI Boundaries: Native interop is where type safety breaks down.
- Standard Library: Historic CVEs in std libs (Python urllib, Java XML, Ruby OpenSSL).
- Package Ecosystem: Typosquatting, dependency confusion, malicious packages.
- Build System: Makefile/gradle/npm script injection during builds.
- Runtime Behavior: Debug vs release differences (Rust overflow, C++ assertions).
- Error Handling: How does the language fail? Silently? With stack traces? Fail-open?
For any language not covered in the reference file: research its specific CWE patterns, CVE history, and known footguns. The examples are entry points, not complete coverage.
When to Apply This Skill
Use this skill when:
- Writing authentication or authorization code
- Handling user input or external data
- Implementing cryptography or password storage
- Reviewing code for security vulnerabilities
- Designing API endpoints
- Building AI agent systems
- Integrating LLMs, RAG pipelines, or function-calling tools (read the LLM/agentic reference)
- Configuring application security settings
- Handling errors and exceptions
- Working with third-party dependencies
- Working in any language: apply the deep analysis mindset above and read the language-quirks reference for the language at hand
1---2name: owasp-security3description: Deep OWASP reference: Top 10 2025, ASVS 5.0, secure patterns, per-language quirks, LLM Top 10 and agentic AI security. Use for an in-depth security review, auth work, or hardening an LLM or agent app. For the everyday baseline use secure-coding.4---56# OWASP Security Best Practices78Apply these security standards when writing or reviewing code.910For deeper material, load on demand:11- [references/language-security-quirks.md](references/language-security-quirks.md): language-specific pitfalls and unsafe/safe patterns for 20 languages (JS/TS, Python, Java, C#, PHP, Go, Ruby, Rust, Swift, Kotlin, C/C++, Scala, R, Perl, Bash, Lua, Elixir, Dart, PowerShell, SQL). Read it when reviewing code in a specific language.12- [references/llm-agentic-security.md](references/llm-agentic-security.md): OWASP Top 10 for LLM Applications (2025) and Agentic AI security (2026), with checklists and code patterns. Read it when the code calls an LLM, builds a RAG pipeline, or wires up an AI agent with tools.1314## Quick Reference: OWASP Top 10:20251516| # | Vulnerability | Key Prevention |17|---|---------------|----------------|18| A01 | Broken Access Control | Deny by default, enforce server-side, verify ownership |19| A02 | Security Misconfiguration | Harden configs, disable defaults, minimize features |20| A03 | Supply Chain Failures | Lock versions, verify integrity, audit dependencies |21| A04 | Cryptographic Failures | TLS 1.2+, AES-256-GCM, Argon2/bcrypt for passwords |22| A05 | Injection | Parameterized queries, input validation, safe APIs |23| A06 | Insecure Design | Threat model, rate limit, design security controls |24| A07 | Auth Failures | MFA, check breached passwords, secure sessions |25| A08 | Integrity Failures | Sign packages, SRI for CDN, safe serialization |26| A09 | Logging Failures | Log security events, structured format, alerting |27| A10 | Exception Handling | Fail-closed, hide internals, log with context |2829## Security Code Review Checklist3031When reviewing code, check for these issues:3233### Input Handling34- [ ] All user input validated server-side35- [ ] Using parameterized queries (not string concatenation)36- [ ] Input length limits enforced37- [ ] Allowlist validation preferred over denylist3839### Authentication & Sessions40- [ ] Passwords hashed with Argon2/bcrypt (not MD5/SHA1)41- [ ] Session tokens have sufficient entropy (128+ bits)42- [ ] Sessions invalidated on logout43- [ ] MFA available for sensitive operations4445### Access Control46- [ ] Check for framework-level auth middleware (e.g. Next.js middleware.ts, proxy.ts, Express middleware) before flagging missing per-route auth47- [ ] Authorization checked on every request48- [ ] Using object references the user cannot manipulate49- [ ] Deny by default policy50- [ ] Privilege escalation paths reviewed5152### Data Protection53- [ ] Sensitive data encrypted at rest54- [ ] TLS for all data in transit55- [ ] No sensitive data in URLs/logs56- [ ] Secrets in environment/vault (not code)5758### Error Handling59- [ ] No stack traces exposed to users60- [ ] Fail-closed on errors (deny, not allow)61- [ ] All exceptions logged with context62- [ ] Consistent error responses (no enumeration)6364## Secure Code Patterns6566### SQL Injection Prevention67```python68# UNSAFE69cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")7071# SAFE72cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))73```7475### Command Injection Prevention76```python77# UNSAFE78os.system(f"convert {filename} output.png")7980# SAFE81subprocess.run(["convert", filename, "output.png"], shell=False)82```8384### Password Storage85```python86# UNSAFE87hashlib.md5(password.encode()).hexdigest()8889# SAFE90from argon2 import PasswordHasher91PasswordHasher().hash(password)92```9394### Access Control95```python96# UNSAFE - No authorization check97@app.route('/api/user/<user_id>')98def get_user(user_id):99 return db.get_user(user_id)100101# SAFE - Authorization enforced102@app.route('/api/user/<user_id>')103@login_required104def get_user(user_id):105 if current_user.id != user_id and not current_user.is_admin:106 abort(403)107 return db.get_user(user_id)108```109110### Error Handling111```python112# UNSAFE - Exposes internals113@app.errorhandler(Exception)114def handle_error(e):115 return str(e), 500116117# SAFE - Fail-closed, log context118@app.errorhandler(Exception)119def handle_error(e):120 error_id = uuid.uuid4()121 logger.exception(f"Error {error_id}: {e}")122 return {"error": "An error occurred", "id": str(error_id)}, 500123```124125### Fail-Closed Pattern126```python127# UNSAFE - Fail-open128def check_permission(user, resource):129 try:130 return auth_service.check(user, resource)131 except Exception:132 return True # DANGEROUS!133134# SAFE - Fail-closed135def check_permission(user, resource):136 try:137 return auth_service.check(user, resource)138 except Exception as e:139 logger.error(f"Auth check failed: {e}")140 return False # Deny on error141```142143## ASVS 5.0 Key Requirements144145### Level 1 (All Applications)146- Passwords minimum 12 characters147- Check against breached password lists148- Rate limiting on authentication149- Session tokens 128+ bits entropy150- HTTPS everywhere151152### Level 2 (Sensitive Data)153- All L1 requirements plus:154- MFA for sensitive operations155- Cryptographic key management156- Comprehensive security logging157- Input validation on all parameters158159### Level 3 (Critical Systems)160- All L1/L2 requirements plus:161- Hardware security modules for keys162- Threat modeling documentation163- Advanced monitoring and alerting164- Penetration testing validation165166## Deep Security Analysis Mindset167168When reviewing any language, think like a senior security researcher:1691701. **Memory Model:** How does the language handle memory? Managed vs manual? GC pauses exploitable?1712. **Type System:** Weak typing = type confusion attacks. Look for coercion exploits.1723. **Serialization:** Every language has a native-object deserializer. All are dangerous with untrusted input.1734. **Concurrency:** Race conditions, TOCTOU, atomicity failures specific to the threading model.1745. **FFI Boundaries:** Native interop is where type safety breaks down.1756. **Standard Library:** Historic CVEs in std libs (Python urllib, Java XML, Ruby OpenSSL).1767. **Package Ecosystem:** Typosquatting, dependency confusion, malicious packages.1778. **Build System:** Makefile/gradle/npm script injection during builds.1789. **Runtime Behavior:** Debug vs release differences (Rust overflow, C++ assertions).17910. **Error Handling:** How does the language fail? Silently? With stack traces? Fail-open?180181**For any language not covered in the reference file:** research its specific CWE patterns, CVE history, and known footguns. The examples are entry points, not complete coverage.182183## When to Apply This Skill184185Use this skill when:186- Writing authentication or authorization code187- Handling user input or external data188- Implementing cryptography or password storage189- Reviewing code for security vulnerabilities190- Designing API endpoints191- Building AI agent systems192- Integrating LLMs, RAG pipelines, or function-calling tools (read the LLM/agentic reference)193- Configuring application security settings194- Handling errors and exceptions195- Working with third-party dependencies196- **Working in any language**: apply the deep analysis mindset above and read the language-quirks reference for the language at hand