Security audit patterns for identifying vulnerabilities and security issues
Use this skill when auditing code for security vulnerabilities or reviewing security-sensitive changes.
When reviewing security-sensitive code, ask:
# Bad
cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")
# Good
cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))
# Bad
os.system(f"convert {filename} output.png")
# Good
subprocess.run(["convert", filename, "output.png"], check=True)
# Bad
open(f"/uploads/{user_filename}")
# Good
safe_path = os.path.realpath(os.path.join("/uploads", user_filename))
if not safe_path.startswith("/uploads/"):
raise ValueError("Invalid path")
# Bad - user controls the URL
response = requests.get(user_provided_url)
# Good - validate against allowlist
ALLOWED_HOSTS = ["api.example.com", "cdn.example.com"]
parsed = urlparse(user_provided_url)
if parsed.hostname not in ALLOWED_HOSTS:
raise ValueError("URL not allowed")
# Bad - arbitrary code execution
data = pickle.loads(user_input)
result = eval(user_expression)
# Good - use safe alternatives
data = json.loads(user_input)
# Bad - algorithm not specified, vulnerable to "none" attack
payload = jwt.decode(token, options={"verify_signature": False})
# Good - explicit algorithm and full validation
payload = jwt.decode(
token,
key=SECRET_KEY,
algorithms=["HS256"],
audience="my-app",
issuer="auth.example.com",
)
# Bad
API_KEY = "sk-1234567890abcdef"
# Good
API_KEY = os.environ["API_KEY"]
# Bad - for security purposes
hashlib.md5(password.encode()).hexdigest()
# Good
import bcrypt
bcrypt.hashpw(password.encode(), bcrypt.gensalt())
Check with:
npm audit / yarn audit (Node.js)pip-audit / safety check (Python)govulncheck (Go)eval(), exec(), or Function()?