secure-code-review skill
Systematically reviews code for SQL injection, XSS, SSRF, broken access control, cryptographic failures, and other common OWASP Top 10 vulnerabilities, providing vulnerable code examples and ready-to-use remediation guidance. Trigger this skill when users ask for a security review, vulnerability scan, or penetration testing assistance, or mention keywords like OWASP, SQL injection, XSS, code audit, or security checklist.
Is the secure-code-review skill safe?
Clean: nothing in its files matched our rules. We read 2 files in the folder on 2026-09-28.
No findings.
Install the secure-code-review skill
A skill is a folder. Copy it into your agent's skills folder and the agent loads it when the task matches its description.
git clone --depth 1 https://github.com/zebbern/claude-code-guide.git /tmp/claude-code-guide mkdir -p ~/.claude/skills cp -r /tmp/claude-code-guide/skills/secure-code-review ~/.claude/skills/secure-code-review
In the Claude apps, zip the folder and upload it from the Skills settings. The folder on GitHub
The instructions your agent would load
SKILL.md as published, without the frontmatter. Read it on GitHub
OWASP Top 10 Code Security Review Checklist
A systematic security review based on the OWASP Top 10 (2021) standard. Each item includes: vulnerability description, typical vulnerable code, inspection checkpoints, and remediation examples. Designed for security-focused code review of web applications.
Usage
Provide the code files or code snippets to review, and specify which OWASP categories to check (or request a full review) to receive an item-by-item audit report.
Example prompts:
- "Check this code for SQL injection risks"
- "Run a full OWASP Top 10 security review on this project"
- "Does this API endpoint have any SSRF vulnerabilities?"
Quick Reference
Review Process SOP
Core principle: prefer false positives over missed true positives.
- Define scope — Identify the files, modules, or code snippets to review
- Full coverage check — Scan through A01-A10 sequentially. Every item must appear in the report (mark items with no findings as pass). The default behavior is to only report issues found — this process requires full coverage to ensure nothing is missed
- Risk classification — Label each finding:
- RED High: Directly exploitable (RCE, SQL injection, SSRF reaching internal networks, plaintext password storage)
- YELLOW Medium: Exploitable under specific conditions (missing rate limiting, weak password policy, static tokens)
- GREEN Low: Defense-in-depth gap with no direct exploitation path (missing security headers, insufficient logging)
- Every finding must include ready-to-use fix code (actual code, not just a description). Reference specific file:line_number
- Output the review report — Use the template below, findings sorted by severity descending, with a prioritized remediation list at the end
A01:2021 — Broken Access Control
Risk: Users can access other users' data or perform unauthorized operations.
Checkpoints:
- [ ] Does every API endpoint enforce authorization?
- [ ] Are there IDOR vulnerabilities (Insecure Direct Object References) — can users access others' data by modifying ID parameters?
- [ ] Do admin interfaces verify roles?
- [ ] Is access control enforced server-side (not just by hiding UI elements)?
- [ ] Is the CORS policy overly permissive?
Vulnerable Code Example
# ❌ Vulnerable: No authorization check — any user can view others' orders by changing user_id
@app.route("/api/orders/<user_id>")
def get_orders(user_id):
orders = db.query(f"SELECT * FROM orders WHERE user_id = {user_id}")
return jsonify(orders)Remediation Example
# ✅ Fixed: Verify the authenticated user can only access their own data
@app.route("/api/orders")
@login_required
def get_orders():
current_user_id = get_current_user().id
orders = db.query("SELECT * FROM orders WHERE user_id = %s", (current_user_id,))
return jsonify(orders)A02:2021 — Cryptographic Failures
Risk: Sensitive data (passwords, credit card numbers, personal information) is unencrypted or uses weak cryptographic algorithms.
Checkpoints:
- [ ] Are passwords stored using secure hashing (bcrypt/scrypt/argon2) rather than MD5/SHA1?
- [ ] Is HTTPS enforced for sensitive data in transit?
- [ ] Are encryption keys hardcoded in the source code?
- [ ] Are deprecated cryptographic algorithms in use (DES, RC4, MD5)?
- [ ] Are sensitive database fields encrypted at rest?
Vulnerable Code Example
# ❌ Vulnerable: MD5 for password storage, hardcoded secret key
import hashlib
SECRET_KEY = "my-secret-key-123"
def save_password(password):
hashed = hashlib.md5(password.encode()).hexdigest()
db.save(hashed)Remediation Example
# ✅ Fixed: bcrypt for password hashing, secret key from environment variable
import bcrypt
import os
SECRET_KEY = os.environ["SECRET_KEY"]
def save_password(password):
salt = bcrypt.gensalt()
hashed = bcrypt.hashpw(password.encode(), salt)
db.save(hashed)A03:2021 — Injection
Risk: User input is concatenated directly into SQL, OS commands, LDAP queries, etc., allowing attackers to execute arbitrary queries or commands.
Checkpoints:
- [ ] Do SQL queries use parameterized queries / ORM (not string concatenation)?
- [ ] Are there os.system() or subprocess.call(shell=True) calls that concatenate user input?
- [ ] Does template rendering properly escape user input (preventing XSS)?
- [ ] Are special characters filtered in LDAP / XPath / NoSQL queries?
- [ ] Are unfiltered user inputs logged directly (log injection)?
SQL Injection — Vulnerable Code
# ❌ Vulnerable: String-concatenated SQL — attacker can input ' OR 1=1 --
@app.route("/api/user")
def get_user():
username = request.args.get("username")
query = f"SELECT * FROM users WHERE username = '{username}'"
result = db.execute(query)
return jsonify(result)SQL Injection — Remediation
# ✅ Fixed: Parameterized query
@app.route("/api/user")
def get_user():
username = request.args.get("username")
result = db.execute(
"SELECT * FROM users WHERE username = %s",
(username,)
)
return jsonify(result)Command Injection — Vulnerable Code
# ❌ Vulnerable: User input concatenated directly into shell command
import os
def ping_host(host):
os.system(f"ping -c 4 {host}")Command Injection — Remediation
# ✅ Fixed: Use subprocess with list arguments, shell disabled
import subprocess
import re
def ping_host(host):
if not re.match(r'^[a-zA-Z0-9.\-]+$', host):
raise ValueError("Invalid hostname")
subprocess.run(["ping", "-c", "4", host], check=True)A04:2021 — Insecure Design
Risk: Business logic design flaws that cannot be fixed by a perfect implementation.
Checkpoints:
- [ ] Do critical operations have rate limiting?
- [ ] Can the password reset flow be abused (username enumeration, verification code brute-force)?
- [ ] Do sensitive operations (payments, transfers) require secondary confirmation?
- [ ] Are there batch operation endpoints with no upper limit?
- [ ] Can business workflows be executed out of order (e.g., skipping payment to complete an order)?
Vulnerable Code Example
# ❌ Vulnerable: No attempt limit on verification code — can be brute-forced
@app.route("/api/verify-code", methods=["POST"])
def verify_code():
code = request.json["code"]
stored_code = session.get("verification_code")
if code == stored_code:
return jsonify({"status": "verified"})
return jsonify({"status": "invalid"}), 400Remediation Example
# ✅ Fixed: Added attempt limit and expiration
@app.route("/api/verify-code", methods=["POST"])
def verify_code():
attempts = session.get("verify_attempts", 0)
if attempts >= 5:
return jsonify({"error": "Too many attempts, please request a new code"}), 429
code = request.json["code"]
stored = session.get("verification_code")
expire_at = session.get("code_expire_at", 0)
if time.time() > expire_at:
return jsonify({"error": "Verification code has expired"}), 400
session["verify_attempts"] = attempts + 1
if code == stored:
session.pop("verify_attempts", None)
return jsonify({"status": "verified"})
return jsonify({"status": "invalid"}), 400A05:2021 — Security Misconfiguration
Risk: Applications or servers use default configurations, enable unnecessary features, or expose sensitive information in error messages.
Checkpoints:
- [ ] Is DEBUG mode disabled in production?
- [ ] Do error pages leak stack traces, database versions, etc.?
- [ ] Are default credentials still in use?
- [ ] Do HTTP responses include security headers (X-Frame-Options, Content-Security-Policy, etc.)?
- [ ] Are unnecessary HTTP methods (PUT, DELETE, TRACE) disabled?
- [ ] Is directory listing disabled?
Vulnerable Code Example
# ❌ Vulnerable: DEBUG enabled in production, leaking sensitive information
app = Flask(__name__)
app.config["DEBUG"] = True
app.config["SECRET_KEY"] = "default-secret"
@app.errorhandler(500)
def error_handler(e):
return jsonify({"error": str(e), "traceback": traceback.format_exc()}), 500Remediation Example
# ✅ Fixed: Configuration from environment variables, DEBUG off in production
import os
app = Flask(__name__)
app.config["DEBUG"] = os.environ.get("FLASK_DEBUG", "false").lower() == "true"
app.config["SECRET_KEY"] = os.environ["FLASK_SECRET_KEY"]
@app.errorhandler(500)
def error_handler(e):
app.logger.error(f"Internal error: {e}")
return jsonify({"error": "Internal server error, please try again later"}), 500A06:2021 — Vulnerable and Outdated Components
Risk: Using third-party libraries or framework versions with known vulnerabilities.
Checkpoints:
- [ ] Do dependencies have known CVEs (scan with pip audit, npm audit, snyk, etc.)?
- [ ] Are there dependencies that haven't been updated in a long time?
- [ ] Are any unmaintained libraries in use?
- [ ] Are lock files (package-lock.json / requirements.txt) under version control?
- [ ] Is there an automated dependency update mechanism (Dependabot, etc.)?
More skills from zebbern/claude-code-guide
- Aacademic-paper-reviewerSimulates academic peer review, evaluating papers across Originality, Methodology, Results, and Writing to provide Major/Minor Revision recommendations with actionable feedback. Triggers when a user asks to \"review my paper,\" \"simulate peer review,\" or \"give my paper a peer review.
- Aactive-directory-attacksThis skill should be used when the user asks to "attack Active Directory", "exploit AD", "Kerberoasting", "DCSync", "pass-the-hash", "BloodHound enumeration", "Golden Ticket", "Silver Ticket", "AS-REP roasting", "NTLM relay", or needs guidance on Windows domain penetration testing.
- Capi-fuzzing-bug-bountyThis skill should be used when the user asks to "test API security", "fuzz APIs", "find IDOR vulnerabilities", "test REST API", "test GraphQL", "API penetration testing", "bug bounty API testing", or needs guidance on API security assessment techniques.
- Aapi-shape-explorerGenerate multiple radically different interface designs for a module using parallel sub-agents. Use when user wants to design an API, explore interface options, compare module shapes, or mentions "design it twice".
- Aaudit-flowInteractive system flow tracing across CODE, API, AUTH, DATA, NETWORK layers with SQLite persistence and Mermaid export. Use for security audits, compliance documentation, flow tracing, feature ideation, brainstorming, debugging, architecture reviews, or incident post-mortems. Triggers on audit, trace flow, document flow, security review, debug flow, brainstorm, architecture review, post-mortem, incident review.
- Aauthentication-patternsAuthentication patterns: session vs JWT vs OAuth comparison, provider selection (NextAuth, Clerk, Supabase Auth), security checklist, and common mistakes. Use when implementing auth, reviewing auth flows, or choosing auth providers.
- Aaws-penetration-testingThis skill should be used when the user asks to "pentest AWS", "test AWS security", "enumerate IAM", "exploit cloud infrastructure", "AWS privilege escalation", "S3 bucket testing", "metadata SSRF", "Lambda exploitation", or needs guidance on Amazon Web Services security assessment.
- Abroken-authenticationThis skill should be used when the user asks to "test for broken authentication vulnerabilities", "assess session management security", "perform credential stuffing tests", "evaluate password policies", "test for session fixation", or "identify authentication bypass flaws". It provides comprehensive techniques for identifying authentication and session management weaknesses in web applications.
- Cburp-suite-testingThis skill should be used when the user asks to "intercept HTTP traffic", "modify web requests", "use Burp Suite for testing", "perform web vulnerability scanning", "test with Burp Repeater", "analyze HTTP history", or "configure proxy for web testing". It provides comprehensive guidance for using Burp Suite's core features for web application security testing.
- AcachingCaching strategies — invalidation, TTL guidelines, cache keys, cache layers, and when not to cache. Use when implementing or reviewing caching logic.
- Achart-imageGenerate publication-quality PNG chart images from data, supporting line, bar, area, candlestick, pie, and heatmap charts. Triggers when the user asks to visualize data, create a graph, plot a time series, or generate a chart for a report, alert, or dashboard. Runs as a lightweight, headless Node.js process without a browser.
- Dcloud-penetration-testingThis skill should be used when the user asks to "perform cloud penetration testing", "assess Azure or AWS or GCP security", "enumerate cloud resources", "exploit cloud misconfigurations", "test O365 security", "extract secrets from cloud environments", or "audit cloud infrastructure". It provides comprehensive techniques for security assessment across major cloud platforms.