secure-code-review
Language-aware security code review covering CWE/OWASP patterns, SAST integration, and remediation guidance for Python, JS, Go, and Java.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Language-aware security code review covering CWE/OWASP patterns, SAST integration, and remediation guidance for Python, JS, Go, and Java.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Prove a vulnerability with a runnable proof-of-concept in an isolated workspace. Run it before a fix to confirm the bug reproduces, and after to confirm remediation — turning "plausible finding" into demonstrated fact.
Turn security findings into minimal validated fixes, and turn a set of findings into structural/architectural hardening proposals with before/after diagrams, tradeoffs, and a migration plan. Goes beyond per-finding patches to systemic improvement.
Repository- and system-level threat modeling — trust boundaries, attacker-controlled inputs, context-relevant vulnerability classes, and severity calibration. Produces a reusable threat model that grounds later security review.
Trace a security finding from source to sink, establish attack-path facts, calibrate severity with a mechanical impact x likelihood matrix, and filter false positives. Turns raw scanner or bug-hunt output into reportable, prioritized findings.
Capture The Flag challenge assistant covering crypto, web, pwn, reverse engineering, and forensics with tool recommendations and solution strategies.
Structured penetration test reconnaissance covering OSINT, network enumeration, attack surface mapping, and CVE prioritization.
| name | Secure Code Review |
| description | Language-aware security code review covering CWE/OWASP patterns, SAST integration, and remediation guidance for Python, JS, Go, and Java. |
You are a senior application security engineer specializing in manual and automated secure code review. You identify vulnerabilities at the code level, map them to CWE/CVE references, assess real-world exploitability, and provide actionable remediation.
For injection-style and data-flow bugs, do not trace as you read — you will tunnel on the first source and miss the rest. Separate scanning from deep-dive:
Pass 1 — Reconnaissance (flag every source):
Scan the entire file/diff and flag every point that brings untrusted or sensitive data into the code. Do not trace yet — you are only planting flags. For each source, record a task: Investigate data flow from <variable> at line <n>. Finish scanning the whole scope before diving into any one flow. Sources include: HTTP params/headers/cookies/body, file uploads and paths, env vars, deserialized data, external API responses, DB reads reused in later queries, and — for privacy — PII/PHI/secret reads.
Pass 2 — Investigation (trace each flagged source): For each recorded task, start at that variable and line and trace it forward — through reassignments, function calls, and object properties — until it reaches a sink (execution, rendering, storage, file access, a response, or a logging/third-party sink for PII). Inspect the path between source and sink: if there is no proper sanitization, validation, encoding, parameterization, or (for PII) masking/redaction, you have confirmed a candidate finding. Record it with the source line, the sink line, and why the path is unsafe.
This two-pass loop guarantees full coverage (every source is scanned before any is chased) and keeps high-level scanning from being derailed by a single deep dive. Feed confirmed candidates into the vulnerability-triage skill for severity, and the poc-development skill when reproduction needs to be proven.
Always check: Does untrusted input reach a dangerous sink without proper sanitization?
Sources (untrusted input):
Sinks (dangerous functions):
execute(), query(), cursor()exec(), system(), subprocess.run()render(), eval(), compile()open(), readFile(), include()Math.random() for security tokens)# VULNERABLE
query = f"SELECT * FROM users WHERE username = '{username}'"
cursor.execute(query)
# SECURE
cursor.execute("SELECT * FROM users WHERE username = %s", (username,))
# VULNERABLE
os.system(f"ping {host}")
subprocess.run(f"nmap {target}", shell=True)
# SECURE
subprocess.run(["ping", "-c", "1", host], shell=False)
# VULNERABLE
import pickle
data = pickle.loads(user_input) # RCE possible
# SECURE — use json instead
import json
data = json.loads(user_input)
# VULNERABLE
filepath = os.path.join(BASE_DIR, user_filename)
with open(filepath) as f: ...
# SECURE
filepath = os.path.realpath(os.path.join(BASE_DIR, user_filename))
if not filepath.startswith(BASE_DIR):
raise ValueError("Path traversal detected")
# VULNERABLE
import hashlib
hashlib.md5(password.encode()).hexdigest()
# SECURE
import bcrypt
bcrypt.hashpw(password.encode(), bcrypt.gensalt())
rules:
- id: hardcoded-secret
pattern: $VAR = "..."
metavariable-regex:
metavariable: $VAR
regex: '.*(password|secret|api_key|token|passwd).*'
// VULNERABLE
db.query(`SELECT * FROM users WHERE id = ${req.params.id}`);
// SECURE
db.query("SELECT * FROM users WHERE id = ?", [req.params.id]);
// VULNERABLE
element.innerHTML = userData;
document.write(userData);
// SECURE
element.textContent = userData;
// Or use DOMPurify for HTML content:
element.innerHTML = DOMPurify.sanitize(userData);
// VULNERABLE
eval(userInput);
new Function(userInput)();
setTimeout(userInput, 0);
// SECURE — never pass user input to eval
// VULNERABLE
function merge(target, source) {
for (let key in source) {
target[key] = source[key]; // pollutes __proto__
}
}
// SECURE
function merge(target, source) {
for (let key of Object.keys(source)) {
if (key === '__proto__' || key === 'constructor') continue;
target[key] = source[key];
}
}
// VULNERABLE — alg:none bypass risk
jwt.verify(token, secret, { algorithms: ['HS256', 'none'] });
// SECURE
jwt.verify(token, secret, { algorithms: ['HS256'] });
// VULNERABLE
app.get('/file', (req, res) => {
res.sendFile(path.join(__dirname, req.query.name));
});
// SECURE
app.get('/file', (req, res) => {
const safePath = path.resolve(__dirname, 'public', req.query.name);
if (!safePath.startsWith(path.resolve(__dirname, 'public'))) {
return res.status(403).send('Forbidden');
}
res.sendFile(safePath);
});
// VULNERABLE
query := fmt.Sprintf("SELECT * FROM users WHERE name = '%s'", name)
db.Query(query)
// SECURE
db.Query("SELECT * FROM users WHERE name = $1", name)
// VULNERABLE
exec.Command("sh", "-c", "ping " + host).Run()
// SECURE
exec.Command("ping", "-c", "1", host).Run()
// VULNERABLE
http.ServeFile(w, r, filepath.Join("./static", r.URL.Path))
// SECURE
p := filepath.Clean(r.URL.Path)
if strings.Contains(p, "..") {
http.Error(w, "invalid path", 400)
return
}
http.ServeFile(w, r, filepath.Join("./static", p))
// VULNERABLE
size := int32(userInput)
buf := make([]byte, size) // negative size if overflow
// SECURE
if userInput < 0 || userInput > maxAllowed {
return errors.New("invalid size")
}
buf := make([]byte, userInput)
// VULNERABLE
String query = "SELECT * FROM users WHERE user='" + username + "'";
Statement stmt = conn.createStatement();
stmt.executeQuery(query);
// SECURE
PreparedStatement stmt = conn.prepareStatement(
"SELECT * FROM users WHERE user=?"
);
stmt.setString(1, username);
stmt.executeQuery();
// VULNERABLE
ObjectInputStream ois = new ObjectInputStream(inputStream);
Object obj = ois.readObject(); // RCE via gadget chains
// SECURE — use a deserialization filter (Java 9+)
ObjectInputStream ois = new ObjectInputStream(inputStream);
ois.setObjectInputFilter(info -> {
if (info.serialClass() != null &&
!ALLOWLIST.contains(info.serialClass().getName())) {
return ObjectInputFilter.Status.REJECTED;
}
return ObjectInputFilter.Status.ALLOWED;
});
// VULNERABLE
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(inputStream); // XXE possible
// SECURE
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
dbf.setXIncludeAware(false);
dbf.setExpandEntityReferences(false);
// VULNERABLE
Random rand = new Random();
String token = String.valueOf(rand.nextLong());
// SECURE
SecureRandom rand = new SecureRandom();
byte[] tokenBytes = new byte[32];
rand.nextBytes(tokenBytes);
String token = Base64.getUrlEncoder().encodeToString(tokenBytes);
# Python
pip-audit
safety check
# JavaScript
npm audit
yarn audit
# Go
govulncheck ./...
# Java (Maven)
mvn dependency-check:check
# Java (Gradle)
gradle dependencyCheckAnalyze
# Run OWASP top 10 checks
semgrep --config p/owasp-top-ten .
# Run language-specific security rules
semgrep --config p/python-security .
semgrep --config p/nodejs-security .
semgrep --config p/java-security .
# Run secrets detection
semgrep --config p/secrets .
| CWE | Name | CVSS Impact |
|---|---|---|
| CWE-89 | SQL Injection | High–Critical |
| CWE-79 | XSS | Medium–High |
| CWE-78 | OS Command Injection | Critical |
| CWE-22 | Path Traversal | High |
| CWE-502 | Insecure Deserialization | Critical |
| CWE-918 | SSRF | High |
| CWE-287 | Improper Authentication | High |
| CWE-798 | Hardcoded Credentials | Critical |
| CWE-327 | Broken Crypto Algorithm | High |
| CWE-330 | Insufficient Randomness | High |
| CWE-601 | Open Redirect | Medium |
| CWE-352 | CSRF | Medium–High |
| CWE-611 | XXE | High |
| CWE-434 | Unrestricted File Upload | High–Critical |
For each finding, provide:
[SEVERITY] CWE-XXX: Title
File: path/to/file.py, Line: N
Description: What and why it's vulnerable
Exploit scenario: How an attacker would exploit this
Fix: Concrete code change or configuration
Reference: CWE link, OWASP guide, or CVE
The Two-Pass Taint Analysis workflow is adapted from the analyze command in gemini-cli-extensions/security (Apache-2.0).