Secure — Security Review
Iron Law
NO DEPLOYMENT WITHOUT SECURITY REVIEW OF ALL CHANGED FILES. Every code change is a potential attack vector.
Process
- Identify security-relevant changes from the diff (auth, DB, API, infra, secrets)
- Run the Checklist below, marking each item as pass, fail, or N/A with reason
- For each failure, cite the file and line number with severity (CRITICAL/HIGH/MEDIUM)
- Report findings using the Evidence Required section
When to Trigger
- Authentication or authorization code changed
- Database queries written or modified
- API endpoints added or changed
- Environment variables or secrets referenced
- File upload, user input parsing, or serialization code
- Infrastructure config (Docker, K8s, CI/CD)
Checklist
Injection
- All user input sanitized/escaped before use in queries — unsanitized input is the #1 attack vector for SQL injection, XSS, and command injection
- Parameterized queries used (no string concatenation in SQL) — string concatenation enables SQL injection even with escaping; parameterized queries are the only safe default
- No
eval(),exec(), or template injection vectors — these functions execute arbitrary code and bypass all input validation
Authentication & Authorization
- Auth checks on every protected endpoint — missing checks on a single endpoint exposes the entire system
- Tokens validated and not just decoded — decoding without signature verification lets attackers forge any token
- Session expiry and refresh logic correct — stale sessions allow account takeover; refresh token rotation prevents replay attacks
- No hardcoded credentials or secrets in code — hardcoded secrets end up in version control and are impossible to rotate
Data Exposure
- Sensitive data not logged (passwords, tokens, PII) — logs are often accessible to more people than the database and persist indefinitely
- API responses don't leak internal details — stack traces, DB schemas, and server versions help attackers craft targeted exploits
- Error messages don't reveal system internals — generic errors in production prevent information disclosure; detailed errors belong in server logs only
-
.envfiles in.gitignore— committed.envfiles expose secrets permanently even after deletion (git history retains them)
Access Control
- RBAC/permissions checked before data access — authorization must happen at the data layer, not just the UI layer, to prevent IDOR and privilege escalation
- No IDOR (Insecure Direct Object Reference) vulnerabilities — replacing an ID in a URL should never grant access to another user's resource
- Rate limiting on authentication endpoints — without rate limiting, brute-force and credential-stuffing attacks are trivial
See references/security.md for the full OWASP Top 10 checklist.
Anti-Rationalization
| Excuse | Rebuttal | What to do instead |
|---|---|---|
| "This is internal-only, no security risk" | Internal tools get exposed. Assume every endpoint is public-facing. | Apply the same security standards as public APIs. |
| "We'll add security later" | Security debt compounds exponentially. Fix it now or pay 10x later. | Build it secure from the start. Retrofitting misses edge cases. |
| "The framework handles security" | Frameworks provide tools, not guarantees. OWASP Top 10 still applies. | Verify framework defaults and add application-layer checks. |
| "Security review is overkill for this" | One missed injection is a breach. Every input surface matters. | Run the checklist. It takes 2 minutes, a breach takes months. |
| "We'll harden it before production" | Security bolted on later is always incomplete. | Build it secure now. Retrofitting misses edge cases. |
| "It's an internal API, no one will abuse it" | Lateral movement attacks start from internal APIs. | Internal does not mean trusted. Validate and authorize every request. |
| "I'll just disable CORS for development" | Dev shortcuts leak into production. | Use a proper CORS allow-list from day one. |
Evidence Required
Before claiming security review is complete, show ALL applicable:
- Checklist above completed: each item marked pass or N/A with reason
- No secrets in code:
grep -r "sk-\|password\s*=" --include="*.{ts,js,py}" .shows clean - Parameterized queries used: show the query code (no string concat)
- Auth checks present on new endpoints: show the middleware/guard
-
.envin.gitignore: confirmed
A blank checklist is not a review. Each item needs a pass or N/A.
Red Flags
- Storing secrets in code or config files committed to git
- Using
HTTPinstead ofHTTPSfor sensitive data eval()or string-concatenated SQL anywhere