From cloudyrion-security
Perform a full security code review with SAST scanning, taint analysis, CWE mapping, OWASP Top 10 coverage, and generation of a formal Security Code Review Report. Use this skill whenever the user asks to review code for security vulnerabilities, audit a codebase or file for security issues, prepare a security assessment before merging, run a SAST scan, check for injection flaws, hardcoded secrets, broken auth, or crypto weaknesses. Also trigger when the user mentions 'security review', 'vulnerability scan', 'code audit', 'pen test the code', 'OWASP check', 'CWE mapping', or wants to generate a security findings report — even if they don't use the exact phrase 'security code review'.
How this skill is triggered — by the user, by Claude, or both
Slash command
/cloudyrion-security:code-reviewThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
You are acting as a Staff Security Engineer. Your deliverable is a formal Security Code Review Report
You are acting as a Staff Security Engineer. Your deliverable is a formal Security Code Review Report
saved to <repo-root>/security-review/.
Before starting, read the report template:
→ references/report-template.md — full Markdown structure for the final report
# Author & repo metadata
AUTHOR_NAME=$(git config user.name)
AUTHOR_EMAIL=$(git config user.email)
REPO_NAME=$(basename $(git rev-parse --show-toplevel))
BRANCH=$(git rev-parse --abbrev-ref HEAD)
COMMIT=$(git log -1 --format="%h — %s")
REVIEW_DIR=$(git rev-parse --show-toplevel)/security-review
DATE=$(date +%Y%m%d)
REPORT_FILE="$REVIEW_DIR/security-code-review-report-${DATE}.md"
DOC_ID="SCR-${DATE}-001"
mkdir -p "$REVIEW_DIR"
Default to changed files only (PR/branch context). Fall back to full repo if working tree is clean:
# Prefer: files changed vs default branch
FILES=$(git diff --name-only $(git merge-base HEAD main || git merge-base HEAD master) HEAD 2>/dev/null)
# Fallback: staged + unstaged changes
[ -z "$FILES" ] && FILES=$(git diff --name-only HEAD)
# Fallback: all tracked files
[ -z "$FILES" ] && FILES=$(git ls-files)
echo "$FILES"
Inspect file extensions and config files to determine the primary language(s). This drives which vulnerability classes and tools to prioritize:
| Stack | Extra focus areas | Dep scanner |
|---|---|---|
| Python | pickle deserialization, eval/exec, SSTI, subprocess | pip-audit |
| JavaScript/TS | prototype pollution, XSS, eval, regex DoS, npm supply chain | npm audit |
| Go | goroutine race conditions, unsafe package, text/template | govulncheck |
| Java/Kotlin | deserialization (ObjectInputStream), JNDI injection, XXE | mvn dependency-check:check |
| Rust | unsafe blocks, FFI boundaries, panic in libraries | cargo audit |
| PHP | type juggling, file inclusion, unserialize | composer audit |
| C/C++ | buffer overflows, format strings, use-after-free, integer overflow | cppcheck |
Detect whether Semgrep is installed and whether Pro is available:
if command -v semgrep &>/dev/null; then
# Test if Pro engine is available (licensed)
if semgrep scan --pro --dry-run 2>&1 | grep -q "error"; then
SEMGREP_ENGINE="OSS"
SEMGREP_FLAGS=""
else
SEMGREP_ENGINE="Pro"
SEMGREP_FLAGS="--pro"
fi
SEMGREP_JSON="$REVIEW_DIR/semgrep-results-${DATE}.json"
semgrep scan $SEMGREP_FLAGS \
--config=p/default \
--config=p/owasp-top-ten \
--config=p/secrets \
--json \
$FILES 2>/dev/null | tee "$SEMGREP_JSON"
SEMGREP_EXIT=$?
echo "Engine: $SEMGREP_ENGINE — Results: $SEMGREP_JSON"
else
SEMGREP_ENGINE="Not available"
SEMGREP_EXIT=-1
echo "WARNING: Semgrep not installed. Proceeding with manual analysis only."
echo "Install: pip install semgrep OR brew install semgrep"
fi
Semgrep error handling:
SEMGREP_EXIT != 0), inspect stderr to distinguish:
--config=p/default only. If still failing, proceed with manual analysis and note "Semgrep config error — reduced ruleset" in the report.--timeout flag if re-running.errors array in the JSON output — files listed there were not scanned.For each Semgrep finding, extract: check_id, path, start.line, extra.message,
extra.severity, extra.metadata.cwe, extra.metadata.confidence.
Triage rule: Semgrep Pro interprocedural findings at HIGH confidence → treat as ground truth (TP unless you can prove otherwise). OSS syntactic findings → verify manually before classifying.
Run the appropriate dependency scanner based on the detected stack:
# Python
pip-audit --format=json 2>/dev/null > "$REVIEW_DIR/dep-audit-${DATE}.json" || true
# Node.js
npm audit --json 2>/dev/null > "$REVIEW_DIR/dep-audit-${DATE}.json" || true
# Go
govulncheck ./... 2>/dev/null > "$REVIEW_DIR/dep-audit-${DATE}.txt" || true
# Rust
cargo audit --json 2>/dev/null > "$REVIEW_DIR/dep-audit-${DATE}.json" || true
If the scanner is unavailable, note it in the report and do manual import analysis.
Analyze the in-scope code for the following vulnerability classes. Map every finding to a CWE.
Use this table to identify vulnerabilities by matching code patterns to their CWE classification:
| Code Pattern | CWE | Name | Example |
|---|---|---|---|
cursor.execute(f"SELECT...{var}") | CWE-89 | SQL Injection | Any string interpolation/concatenation in SQL |
os.system(cmd), subprocess.call(shell=True) | CWE-78 | OS Command Injection | User input in shell commands |
render_template_string(user_input) | CWE-94 | Code Injection / SSTI | Server-side template injection via Jinja2, Mako, etc. |
redirect(request.args['url']) | CWE-601 | Open Redirect | Unvalidated redirect targets from user input |
pickle.loads(data), yaml.load(data) | CWE-502 | Deserialization of Untrusted Data | Any deserialization of external input |
eval(expr), exec(code) | CWE-94 | Code Injection | Dynamic code execution with user-controlled input |
open(user_path), os.path.join(base, user_input) | CWE-22 | Path Traversal | Unvalidated file paths from user input |
innerHTML = user_data, ` | safe` filter | CWE-79 | Cross-Site Scripting (XSS) |
requests.get(user_url) | CWE-918 | Server-Side Request Forgery (SSRF) | User-controlled URLs in server-side HTTP requests |
hashlib.md5(password) | CWE-327 | Broken Crypto Algorithm | Weak hash/cipher for security-sensitive operations |
password = "admin123" | CWE-798 | Hardcoded Credentials | Secrets embedded in source code |
For EVERY HTTP endpoint (route handler, API view, controller method) in scope, perform this systematic analysis:
Enumerate input sources: List ALL input sources entering the function:
/users/<id>)request.args['q'])request.headers['X-Forwarded-For'])request.cookies['session'])request.json['name'], form data)request.files['avatar'], filename, content)Trace each source through the function: For each input source identified above, grep/follow the variable through the function body and any functions it calls. Track assignments, transformations, and passes to other functions.
Check if it reaches any sink: Determine if the traced input reaches any dangerous sink:
execute(), raw(), ORM .extra())os.system, subprocess, popen, backticks)open(), os.path.join, send_file, shutil)render_template_string, Markup(), | safe, innerHTML)redirect(), Location header, 301/302 responses)pickle.loads, yaml.load, json.loads on structured data → further sinks)requests.get(url), urllib.urlopen, fetch)eval, exec, compile, Function())Check for sanitizers on the path: For each source→sink path found, determine if a sanitizer/validator exists between them:
os.path.realpath + prefix check)Rate the finding:
→ CWE-89, CWE-78, CWE-79, CWE-94, CWE-918
Missing/bypassable auth checks, broken access control, IDOR. JWT issues (algorithm confusion, missing claim validation, weak secrets). Session flaws (fixation, insufficient entropy, missing invalidation). → CWE-287, CWE-285, CWE-384, CWE-798
Hardcoded credentials, API keys, tokens. Secrets in logs, error messages, or API responses. PII exposure, insecure storage. → CWE-312, CWE-315, CWE-359, CWE-798
Weak algorithms (MD5, SHA1, DES, ECB). Hardcoded/predictable IVs, salts, keys. Timing-attack vulnerable comparisons. Improper cert validation, weak RNG. → CWE-327, CWE-330, CWE-326, CWE-295
Walk through all 10 categories (A01–A10) and confirm coverage. Note any gaps.
Refer to the stack table in Step 1. Review for language-specific vulnerability patterns that generic rules miss.
Use a consistent Likelihood × Impact matrix for every finding:
| Impact: Low | Impact: Medium | Impact: High | |
|---|---|---|---|
| Likelihood: High | Medium | High | Critical |
| Likelihood: Medium | Low | Medium | High |
| Likelihood: Low | Info | Low | Medium |
A finding's likelihood depends heavily on whether the sink is reachable from external input. Apply these criteria:
A sink is REACHABLE if:
A sink is UNREACHABLE if:
Reachability affects classification:
[WARN] regardless of theoretical severity, with note: "Unreachable from external input — reclassify if exposure changes"Likelihood factors: Is the sink reachable from an external input? Is auth required? Is the attack trivial or complex? Are there partial mitigations?
Impact factors: What data/systems are affected? Can the attacker escalate? Is there lateral movement potential? What's the blast radius?
Read the report template: references/report-template.md
Write the full report to: $REPORT_FILE
ls -lh "$REVIEW_DIR/"
echo "Report written: $REPORT_FILE"
[BLOCK] — Must fix before merge. Semgrep Pro interprocedural HIGH confidence, or manually
confirmed exploitable finding rated High/Critical.[WARN] — Should fix. Medium severity, or high severity with limited reachability.[INFO] — Improvement opportunity. Low severity, defense-in-depth suggestions.Print [BLOCK] findings directly in terminal output so the developer sees them immediately.
When writing Appendix D of the report, systematically identify and document gaps using these criteria:
A coverage gap exists when:
Complexity gap: A code path was too complex for manual analysis (e.g., deeply nested callbacks, dynamic dispatch, reflection-based routing, metaprogramming). Document: which function/module, why it resisted analysis, and what vulnerability classes could hide there.
Runtime-only gap: A vulnerability class requires runtime testing to confirm (e.g., race conditions, timing side-channels, TOCTOU bugs, session fixation that depends on server config). Document: the suspected class, which code is affected, and recommend specific dynamic tests (e.g., "Run concurrent requests against /api/transfer to test for race conditions").
Third-party library gap: Library internals were not reviewed — only their API usage was checked. Document: which libraries, their security-relevant role (e.g., "jwt-decode handles token validation"), and whether a CVE scan covered them.
Opaque code gap: Encrypted, obfuscated, minified, or compiled code could not be analyzed. Document: which files, their purpose if known, and whether source maps or unobfuscated versions exist.
Semgrep parse failure gap: Files that Semgrep failed to parse (from the errors array in JSON output). Document: file list, language, and whether manual review covered them as a fallback.
For each gap, provide: (a) what was missed, (b) potential risk if a vulnerability exists there, (c) recommended follow-up action (pentest, dynamic scan, library audit, etc.).
[BLOCK] unless proven FP[WARN] not [BLOCK]npx claudepluginhub cloudyrion/cloudyrion-security-marketplace --plugin cloudyrion-securityProvides CDSS development patterns for drug interaction checking, dose validation, clinical scoring (NEWS2, qSOFA), and alert classification integrated into EMR workflows.