| name | owasp-security |
| description | Security review: OWASP Top 10:2025, ASVS 5.0, Agentic AI 2026, LLM Top 10, API/CICD, NIST 800-63B-4, WebAuthn, OAuth 2.1, FAPI 2.0, post-quantum. Triggers: "security review", "OWASP", "vulnerability check", "auth code", "threat model", "MCP security". Skip for general code review. |
OWASP Security Best Practices Skill
Apply these security standards when writing or reviewing code.
Scope & limits. This skill is a checklist-guided review assistant over
the standards below — useful for sweeping a diff or PR and surfacing
high-signal findings. It is not, and does not replace, a formal audit,
pentest, or certification: the breadth of the catalog (10+ frameworks) means
checklist coverage, not exhaustive verification. Use it to raise the security
floor and to prioritize; treat findings as starting points, not verdicts.
Deep references
This file is the operational entry point — quick checklists and code patterns. For deep coverage of any topic below, open the matching file in references/:
The full historical reference document with deeper background on Top 10:2025, ASVS 5.0, and Agentic 2026 is in OWASP-2025-2026-Report.md.
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
Deep dive: references/auth-modern.md
Access Control
Data Protection
Deep dive: references/crypto-modern.md
Error Handling
Secure Code Patterns
SQL Injection Prevention
cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
Command Injection Prevention
os.system(f"convert {filename} output.png")
subprocess.run(["convert", filename, "output.png"], shell=False)
Password Storage
hashlib.md5(password.encode()).hexdigest()
from argon2 import PasswordHasher
PasswordHasher().hash(password)
Access Control
@app.route('/api/user/<user_id>')
def get_user(user_id):
return db.get_user(user_id)
@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
@app.errorhandler(Exception)
def handle_error(e):
return str(e), 500
@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
def check_permission(user, resource):
try:
return auth_service.check(user, resource)
except Exception:
return True
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
LLM & Agentic AI Security
Two complementary OWASP lists apply when building AI-powered systems:
OWASP Top 10 for LLM Applications 2025 — model-boundary risks:
| ID | Risk | One-line |
|---|
| LLM01 | Prompt Injection | Direct or indirect (via tool output / RAG / docs) |
| LLM02 | Sensitive Info Disclosure | PII / secrets leaked via outputs |
| LLM03 | Supply Chain | Compromised models, fine-tunes, LoRA adapters |
| LLM04 | Data / Model Poisoning | Training-data tampering, backdoors |
| LLM05 | Improper Output Handling | Downstream systems trust LLM output unchecked |
| LLM06 | Excessive Agency | Too much functionality / permission / autonomy |
| LLM07 | System Prompt Leakage | System prompts treated as secrets, but extractable |
| LLM08 | Vector / Embedding Weaknesses | RAG poisoning, embedding inversion, cross-tenant leak |
| LLM09 | Misinformation | Hallucinations propagated as fact |
| LLM10 | Unbounded Consumption | Token / resource / cost exhaustion |
OWASP Top 10 for Agentic Applications 2026 — system-level risks:
| ID | Risk | Mitigation |
|---|
| ASI01 | Goal Hijack | Boundaries, output schemas, behavior monitoring |
| ASI02 | Tool Misuse | Least privilege, schemas on I/O, audit |
| ASI03 | Privilege Abuse | Short-lived scoped tokens, delegated identity |
| ASI04 | Supply Chain | Sign packages, sandbox MCP servers, allowlist |
| ASI05 | Code Execution | Sandbox, static analysis, human approval |
| ASI06 | Memory Poisoning | Validate at ingest + retrieve, trust segmentation |
| ASI07 | Inter-Agent Comms | Authenticate, encrypt, message integrity |
| ASI08 | Cascading Failures | Circuit breakers, degradation, isolation |
| ASI09 | Trust Exploitation | Label AI content, verification steps |
| ASI10 | Rogue Agents | Behavior baseline, kill switch, anomaly alerts |
Modern attack patterns to watch (2025-2026)
- Indirect prompt injection — Google reported +32% rise in indirect injection attempts targeting AI browsers / agents (Nov-2025 → Feb-2026). Carriers: web pages, PDFs, calendar invites, emails.
- Many-shot jailbreaking — exploits long context (>128k tokens) by stuffing fake "user/assistant" turns. Cap effective context for safety decisions; classify the full assembled prompt.
- Tool-empowered jailbreaks — model refuses individual harmful asks but chains tools (
fetch → write_file → send_email) where no single call looks malicious. Model trajectories, not just calls.
Agent / LLM Security Checklist
Deep dive: references/llm-agentic.md
ASVS 5.0 Key Requirements
ASVS 5.0 has 17 categories (V1-V17). V15 OAuth/OIDC, V16 Self-Contained Tokens, V17 WebSockets are new in 5.0.
Level 1 (All Applications)
- Passwords minimum 15 characters at AAL2 (NIST 800-63B-4); 8 at AAL1
- Check against breached password lists (mandatory, was "should" in 800-63B-3)
- Rate limiting on authentication
- Session tokens 128+ bits entropy
- HTTPS everywhere; HSTS
Level 2 (Sensitive Data)
- All L1 requirements plus:
- Passkeys (WebAuthn) or hardware-bound MFA preferred over TOTP/SMS
- Cryptographic key management with rotation
- Comprehensive security logging (structured, tamper-evident)
- Input validation on all parameters (server-side, schema-based)
- Session monitoring (anomaly detection, step-up auth)
Level 3 (Critical Systems)
- All L1/L2 requirements plus:
- Hardware security modules for keys
- FAPI 2.0 for high-stakes APIs
- Threat modeling documentation (STRIDE / MAESTRO for AI systems)
- Advanced monitoring and alerting
- Penetration testing validation
- Crypto-agility for post-quantum migration readiness
API & CI/CD Quick Refs
When the review focuses on APIs or build/deploy pipelines, the general Top 10 isn't enough. Use the dedicated lists:
OWASP API Security Top 10:2023 (still current in 2026):
- API1 BOLA · API2 Broken Auth · API3 BOPLA (mass assignment) · API4 Unrestricted Resource Consumption · API5 BFLA · API6 Sensitive Business Flow Abuse · API7 SSRF · API8 Misconfiguration · API9 Improper Inventory · API10 Unsafe Third-Party Consumption
OWASP CI/CD Top 10:
- CICD-SEC-1 Flow Control · -2 IAM · -3 Dependency Chain Abuse · -4 Poisoned Pipeline Execution (PPE) · -5 Pipeline-Based Access · -6 Credential Hygiene · -7 System Misconfig · -8 3rd-Party Usage · -9 Artifact Integrity · -10 Logging
Deep dive: references/api-cicd.md
CWE Top 25:2025 (CISA / MITRE, Dec-2025)
Top 5 most-exploited weaknesses observed in CVEs over 24 months:
- CWE-79 Cross-site Scripting
- CWE-787 Out-of-bounds Write
- CWE-89 SQL Injection
- CWE-352 CSRF
- CWE-862 Missing Authorization (+5 positions vs 2024)
Use to prioritize SAST rules and developer training. Full list + OWASP mapping: references/extras.md
Language-Specific Security Quirks
Important: The examples below are illustrative starting points, not exhaustive. When reviewing code, think like a senior security researcher: consider the language's memory model, type system, standard library pitfalls, ecosystem-specific attack vectors, and historical CVE patterns. Each language has deeper quirks beyond what's listed here.
Different languages have unique security pitfalls. Here are the top 20 languages with key security considerations. Go deeper for the specific language you're working in:
JavaScript / TypeScript
Main Risks: Prototype pollution, XSS, eval injection
Object.assign(target, userInput)
Object.assign(Object.create(null), validated)
eval(userCode)
Watch for: eval(), innerHTML, document.write(), prototype chain manipulation, __proto__
Python
Main Risks: Pickle deserialization, format string injection, shell injection
pickle.loads(user_data)
json.loads(user_data)
query = "SELECT * FROM users WHERE name = '%s'" % user_input
cursor.execute("SELECT * FROM users WHERE name = %s", (user_input,))
Watch for: pickle, eval(), exec(), os.system(), subprocess with shell=True
Java
Main Risks: Deserialization RCE, XXE, JNDI injection
ObjectInputStream ois = new ObjectInputStream(userStream);
Object obj = ois.readObject();
ObjectMapper mapper = new ObjectMapper();
mapper.readValue(json, SafeClass.class);
Watch for: ObjectInputStream, Runtime.exec(), XML parsers without XXE protection, JNDI lookups
C#
Main Risks: Deserialization, SQL injection, path traversal
BinaryFormatter bf = new BinaryFormatter();
object obj = bf.Deserialize(stream);
var obj = JsonSerializer.Deserialize<SafeType>(json);
Watch for: BinaryFormatter, JavaScriptSerializer, TypeNameHandling.All, raw SQL strings
PHP
Main Risks: Type juggling, file inclusion, object injection
if ($password == $stored_hash) { ... }
if (hash_equals($stored_hash, $password)) { ... }
include($_GET['page'] . '.php');
$allowed = ['home', 'about']; include(in_array($page, $allowed) ? "$page.php" : 'home.php');
Watch for: == vs ===, include/require, unserialize(), preg_replace with /e, extract()
Go
Main Risks: Race conditions, template injection, slice bounds
go func() { counter++ }()
atomic.AddInt64(&counter, 1)
template.HTML(userInput)
{{.UserInput}}
Watch for: Goroutine data races, template.HTML(), unsafe package, unchecked slice access
Ruby
Main Risks: Mass assignment, YAML deserialization, regex DoS
User.new(params[:user])
User.new(params.require(:user).permit(:name, :email))
YAML.load(user_input)
YAML.safe_load(user_input)
Watch for: YAML.load, Marshal.load, eval, send with user input, .permit!
Rust
Main Risks: Unsafe blocks, FFI boundary issues, integer overflow in release
unsafe { ptr::read(user_ptr) }
let x: u8 = 255;
let y = x + 1;
let y = x.checked_add(1).unwrap_or(255);
Watch for: unsafe blocks, FFI calls, integer overflow in release builds, .unwrap() on untrusted input
Swift
Main Risks: Force unwrapping crashes, Objective-C interop
let value = jsonDict["key"]!
guard let value = jsonDict["key"] else { return }
String(format: userInput, args)
Watch for: force unwrap (!), try!, ObjC bridging, NSSecureCoding misuse
Kotlin
Main Risks: Null safety bypass, Java interop, serialization
val len = javaString.length
val len = javaString?.length ?: 0
clazz.getDeclaredMethod(userInput)
Watch for: Java interop nulls (! operator), reflection, serialization, platform types
C / C++
Main Risks: Buffer overflow, use-after-free, format string
char buf[10]; strcpy(buf, userInput);
strncpy(buf, userInput, sizeof(buf) - 1);
printf(userInput);
printf("%s", userInput);
Watch for: strcpy, sprintf, gets, pointer arithmetic, manual memory management, integer overflow
Scala
Main Risks: XML external entities, serialization, pattern matching exhaustiveness
// UNSAFE: XXE
val xml = XML.loadString(userInput)
// SAFE: Disable external entities
val factory = SAXParserFactory.newInstance()
factory.setFeature("http://xml.org/sax/features/external-general-entities", false)
Watch for: Java interop issues, XML parsing, Serializable, exhaustive pattern matching
R
Main Risks: Code injection, file path manipulation
eval(parse(text = user_input))
read.csv(paste0("data/", user_file))
if (grepl("^[a-zA-Z0-9]+\\.csv$", user_file)) read.csv(...)
Watch for: eval(), parse(), source(), system(), file path manipulation
Perl
Main Risks: Regex injection, open() injection, taint mode bypass
$input =~ /$user_pattern/;
$input =~ /\Q$user_pattern\E/;
open(FILE, $user_file);
open(my $fh, '<', $user_file);
Watch for: Two-arg open(), regex from user input, backticks, eval, disabled taint mode
Shell (Bash)
Main Risks: Command injection, word splitting, globbing
rm $user_file
rm "$user_file"
eval "$user_command"
Watch for: Unquoted variables, eval, backticks, $(...) with user input, missing set -euo pipefail
Lua
Main Risks: Sandbox escape, loadstring injection
loadstring(user_code)()
Watch for: loadstring, loadfile, dofile, os.execute, io library, debug library
Elixir
Main Risks: Atom exhaustion, code injection, ETS access
# UNSAFE: Atom exhaustion DoS
String.to_atom(user_input)
# SAFE: Use existing atoms only
String.to_existing_atom(user_input)
# UNSAFE: Code injection
Code.eval_string(user_input)
# SAFE: Never eval user input
Watch for: String.to_atom, Code.eval_string, :erlang.binary_to_term, ETS public tables
Dart / Flutter
Main Risks: Platform channel injection, insecure storage
// UNSAFE: Storing secrets in SharedPreferences
prefs.setString('auth_token', token);
// SAFE: Use flutter_secure_storage
secureStorage.write(key: 'auth_token', value: token);
Watch for: Platform channel data, dart:mirrors, Function.apply, insecure local storage
PowerShell
Main Risks: Command injection, execution policy bypass
# UNSAFE: Injection
Invoke-Expression $userInput
# SAFE: Avoid Invoke-Expression with user data
# UNSAFE: Unvalidated path
Get-Content $userPath
# SAFE: Validate path is within allowed directory
Watch for: Invoke-Expression, & $userVar, Start-Process with user args, -ExecutionPolicy Bypass
SQL (All Dialects)
Main Risks: Injection, privilege escalation, data exfiltration
"SELECT * FROM users WHERE id = " + userId
Watch for: Dynamic SQL, EXECUTE IMMEDIATE, stored procedures with dynamic queries, privilege grants
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 its pickle/Marshal equivalent. All are dangerous.
- 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 listed: Research its specific CWE patterns, CVE history, and known footguns. The examples above are entry points, not complete coverage.
Gotchas
Always check for framework-level auth BEFORE flagging missing per-route auth
The most common false positive: flagging a route handler as "no auth check" when auth is enforced globally in middleware (Next.js middleware.ts, Express app.use, Chi middleware stack, FastAPI dependencies). Read the middleware config before reporting.
Fail-closed is MANDATORY in permission checks
return True in the except branch of a permission check is the most critical vulnerability pattern you will see. Auth failure must deny, not grant. This is not a style preference.
The language examples are starting points, not a complete checklist
Every language has deeper quirks than what is listed (memory model, type system, serialization traps, FFI boundaries, historic CVEs in std lib). For any language you review, apply the deep analysis mindset — do not stop at the top-line examples.
OWASP Top 10 has versions — use 2025/2026, not 2021
Top 10:2025 reordered and added categories (Supply Chain moved up; Exception Handling is now A10). Citing 2021 rankings gives stale advice. Same applies to ASVS (5.0 is current).
Input validation is server-side, period
Client-side validation is UX, not security. Every reference to "validated input" in the checklist assumes server-side enforcement. If code only validates in the browser, it is unvalidated.
Agentic AI threats are not hypothetical
Prompt injection (ASI01), tool misuse (ASI02), memory poisoning (ASI06) are actively exploited in 2026. When reviewing agent code, apply the ASI checklist — do not treat it as forward-looking only. Indirect prompt injection (via fetched web pages / docs / tool output) is the dominant vector — it bypasses input-sanitization mindsets built for user-typed prompts.
Don't require periodic password rotation
NIST SP 800-63B-4 (final 31-Jul-2025) says passwords SHALL NOT be required to rotate on a schedule. Rotate only on evidence of compromise. Also: no composition rules ("must have a digit"), no password hints, no knowledge-based recovery. If you see "change your password every 90 days" in a fresh design, flag it.
Passkeys before generic MFA
When recommending "add MFA", first ask whether passkeys (WebAuthn) fit. Passkeys are phishing-resistant and AAL2 by themselves (with userVerification). Password + TOTP is still relayable via reverse-proxy phishing kits — it's better than nothing, but not the default recommendation for new builds anymore.
MCP servers need OAuth 2.1 + RFC 8707 + DPoP
MCP authorization spec (Jun-2025) is not optional theory. Tokens must carry resource indicators (RFC 8707) scoped to the specific MCP server, and DPoP sender-constraining prevents stolen-token replay. "Confused deputy" attacks in MCP proxies are the canonical failure mode.
Start PQC inventory now if you store long-lived secrets
Harvest-now-decrypt-later means anything encrypted today with RSA / ECDH and stored by an adversary is at risk once a sufficient quantum computer arrives (~2030-2035 mainstream estimate). For new systems handling secrets that must remain confidential past 2035, plan crypto-agility now; for systems already in production, inventory and prioritize. FIPS 203/204/205 are the standards.
LLM Top 10:2025 and Agentic 2026 are complementary, not alternative
A real agent application has BOTH model-boundary risks (LLM Top 10 — prompt injection, output handling, system prompt leakage, RAG poisoning) AND system-level risks (Agentic — tool misuse, privilege abuse, cascading failures). Applying only one list leaves the other surface unreviewed.
When to Apply This Skill
Use this skill when: