Code review checklist for security
Last updated
A security code review checks the places where untrusted input, identity, or secrets cross a boundary. These are the blocking security checks from the stable cards, from a single function up to the dependency pipeline. Each card names the organisations behind it.
The checks
- svc-sqli-authn [block]: Pass untrusted data to queries as bound parameters, never by string concatenation or formatting.
- fn-no-shell-with-input [block]: Start processes with the program and each argument as separate list items, and never through a shell string.
- fn-no-raw-html-sink [block]: Write untrusted text through an encoding sink (
textContent, auto-escaped template), never through a raw HTML sink. - fn-object-level-authz [block]: Check that the caller may act on the specific record before returning or changing it.
- svc-authz-central-deny-default [block]: Route every request through one authorization layer that denies when no rule allows it.
- svc-csrf-state-changing [block]: Require a CSRF token (or an equivalent header check) on every cookie-authenticated request that changes state, and never change state on GET.
- svc-session-lifecycle [block]: Issue a new session ID at login, and set
Secure,HttpOnlyandSameSiteon the session cookie. - svc-auth-throttle-generic-errors [block]: Limit failed attempts per account, and return the same message and status code whether or not the account exists.
- fn-confine-file-path [block]: Resolve the final path and check that it stays inside the intended base directory before using it.
- svc-upload-validate-store [block]: Allowlist the file type, cap the size, and store each upload under a generated name where the server will not execute it.
- sys-ssrf [block]: Fetch a user-supplied URL only when its host matches a server-side allowlist.
- sys-secrets-and-errors [block]: Fail closed: a validation or auth error must deny, never continue, and an error response must not carry internals such as stack traces, SQL or tokens.
- code-secret-scan [block]: Scan for committed credentials, and treat any hit as leaked: revoke and replace it first. With no scanner present and no secret found, the FAIL is the missing control; evidence is "absent in <paths>". A platform scanner (GitHub secret scanning with push protection, GitLab secret detection) counts when it is enabled on the repo and covers history.
- code-dependency-pinning [block]: Commit a lockfile with hashes and install from it in CI.
Run them
To run these checks, paste Read https://goodcodereview.com/llms.txt and use it to review my code. to your agent, or work through them by hand. Every stable security card, including the should-fix ones, is on the security concern page.