code-auditor — a real code review, not a vibe check
When to use this skill
Trigger when the user wants a judgment call on code quality. Strong signals:
- "review this", "audit this codebase", "find bugs", "what's wrong with this PR"
- A pasted diff with no further instructions
- After a long implementation session, before commit
- "is this safe to ship?"
Do not trigger for: pure style/formatting (linters do that), generating fixes (use refactor-master), or for security-only reviews where the user explicitly wants OWASP coverage (use security-sentinel).
The output contract
A report with:
- Verdict — one line: safe to ship / needs changes / blocks merge
- Critical issues — bugs, security, data loss risks. Each with
file:line, what's wrong, how to fix, why it matters
- High-priority — performance, correctness edge cases, broken contracts
- Medium — maintainability problems that will hurt the next person
- Notes — stylistic suggestions, optional improvements
If there are zero criticals and zero highs, say so. Don't manufacture findings to fill the report.
Workflow
1 — Scope
Ask, or infer:
- Is this a diff review (compare against
main) or a full-file audit?
- Which areas matter most: correctness, security, performance, maintainability?
- Is there a target reader (the author, the team lead, a release gate)?
If reviewing a diff, run git diff <base>...HEAD first. Don't audit the whole repo when the user only changed one function.
2 — Read the code with intent
Walk the changed code with these lenses:
Correctness lens — what does this function promise, and does it deliver?
- Off-by-one in loops or slicing
- Null/undefined paths the type system doesn't cover (e.g. JSON parse, regex match)
- Async without await; awaits in loops where Promise.all should be
- Mutated inputs (especially arrays and objects passed by reference)
- Race conditions: shared state, parallel writes, double-clicks, retry on top of side effects
- Date/time/timezone handling
- Float comparison without epsilon
Security lens — what's the attack surface?
- User input flowing into SQL, shell, file paths, HTML, regex, JSON, YAML
- Auth checks missing on new endpoints
- Secrets in code, env files committed, logs, error messages
- CORS too permissive; CSRF on state-changing forms
- Open redirects, SSRF via user-controlled URLs
- Trust boundaries crossed without revalidation
Performance lens — what's wasteful?
- N+1 queries (any
.map(async ...) over IDs that hits the DB)
- Unbounded loops, recursion without depth limit
- Synchronous file/IO on hot paths
- Unmemoized renders, re-instantiated event handlers in JSX
- Loading entire collections to compute a count/exists check
Maintainability lens — will the next engineer cry?
- Functions over ~60 lines or with > 3 levels of nesting
- Boolean flags that should be enums
- Comments explaining what (delete) vs why (keep)
- Dead code; unreachable branches; commented-out blocks
- Names that lie (
getUser that creates a user, validate that mutates)
3 — Cross-check assumptions
For each finding, before writing it up:
- Read the surrounding context. Sometimes the "bug" is intentional.
- Search for callers. A function that looks unsafe may only be called from a safe site.
- Check tests. If the behavior is covered, the finding may be by design.
4 — Rank and write
Order findings by blast radius, not by where they appear in the file. A silent data-loss bug on line 412 beats a missing prop type on line 3.
For each finding, write:
[SEVERITY] file:line — one-line title
What: the actual problem in 1–2 sentences
Why it matters: the user-visible impact (data loss, security, perf)
Fix: the smallest change that resolves it (or a sketch in 3 lines of code)
Don't suggest rewrites unless the file is genuinely beyond repair. Patch-shaped feedback gets fixed; rewrite suggestions get ignored.
5 — Verdict
End with the one-line verdict. Be decisive. "Looks fine, ship it" is a valid output. So is "Don't merge — issue #2 will corrupt user data on retry."
Patterns and anti-patterns
✅ Do:
- Cite
file:line. Reviews without citations don't get acted on.
- Group findings by file when there are many. Easier to address as a batch.
- Compliment the good parts when they're genuinely good — anchors the trust the rest of the review needs.
❌ Don't:
- Don't pad with nits to look thorough. Three real findings beat thirty fake ones.
- Don't review style if the repo has a formatter. The formatter will do it.
- Don't make confident security claims without tracing the data flow. Hedge if you're not sure: "this may be SQL injection — please verify the ORM is parameterizing here."
- Don't suggest a refactor in a bug-fix review. Note it separately.
Example invocation
User: "Review this PR for the new password reset endpoint." [pastes diff]
- Scope: a diff review, security-sensitive, ~80 lines across 3 files.
- Read with correctness + security lenses prioritized.
- Findings:
- [CRITICAL]
src/auth/reset.ts:42 — token comparison uses ===, not crypto.timingSafeEqual. Timing-attack vulnerable. Use crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b)).
- [HIGH]
src/auth/reset.ts:67 — no rate limit on the request endpoint. Attacker can enumerate emails. Add the existing rateLimit('auth.reset', { max: 5, window: '15m' }) middleware.
- [MED]
src/auth/reset.ts:88 — error message reveals whether the email exists. Return the same response for "sent" and "not found".
- [NOTE] Token TTL is hard-coded to 1 hour. Consider extracting to
config/auth.ts so it's tunable.
- Verdict: blocks merge — fix the timing-safe compare and the rate limit. Other items can land in a follow-up.
See also
security-sentinel — when the review is purely security-focused (OWASP sweep)
refactor-master — to actually apply the structural fixes the audit suggests
test-architect — to add coverage for the edge cases the audit found
1---2name: code-auditor3description: Run a structured review of a diff, file, module, or full codebase. Surfaces correctness bugs, security gaps, performance issues, and maintainability smells with file:line citations and severity rankings. Use when the user says "review this code", "audit this", "find bugs in", "what's wrong with this", "code review", or pastes a diff and asks for feedback. Output is a prioritized punch list, not a wall of nits.4---56# code-auditor — a real code review, not a vibe check78## When to use this skill910Trigger when the user wants a *judgment call* on code quality. Strong signals:1112- "review this", "audit this codebase", "find bugs", "what's wrong with this PR"13- A pasted diff with no further instructions14- After a long implementation session, before commit15- "is this safe to ship?"1617Do *not* trigger for: pure style/formatting (linters do that), generating fixes (use `refactor-master`), or for security-only reviews where the user explicitly wants OWASP coverage (use `security-sentinel`).1819## The output contract2021A report with:22231. **Verdict** — one line: safe to ship / needs changes / blocks merge242. **Critical issues** — bugs, security, data loss risks. Each with `file:line`, what's wrong, how to fix, why it matters253. **High-priority** — performance, correctness edge cases, broken contracts264. **Medium** — maintainability problems that will hurt the next person275. **Notes** — stylistic suggestions, optional improvements2829If there are zero criticals and zero highs, say so. Don't manufacture findings to fill the report.3031## Workflow3233### 1 — Scope3435Ask, or infer:36- Is this a diff review (compare against `main`) or a full-file audit?37- Which areas matter most: correctness, security, performance, maintainability?38- Is there a target reader (the author, the team lead, a release gate)?3940If reviewing a diff, run `git diff <base>...HEAD` first. Don't audit the whole repo when the user only changed one function.4142### 2 — Read the code with intent4344Walk the changed code with these lenses:4546**Correctness lens** — what does this function promise, and does it deliver?47- Off-by-one in loops or slicing48- Null/undefined paths the type system doesn't cover (e.g. JSON parse, regex match)49- Async without await; awaits in loops where Promise.all should be50- Mutated inputs (especially arrays and objects passed by reference)51- Race conditions: shared state, parallel writes, double-clicks, retry on top of side effects52- Date/time/timezone handling53- Float comparison without epsilon5455**Security lens** — what's the attack surface?56- User input flowing into SQL, shell, file paths, HTML, regex, JSON, YAML57- Auth checks missing on new endpoints58- Secrets in code, env files committed, logs, error messages59- CORS too permissive; CSRF on state-changing forms60- Open redirects, SSRF via user-controlled URLs61- Trust boundaries crossed without revalidation6263**Performance lens** — what's wasteful?64- N+1 queries (any `.map(async ...)` over IDs that hits the DB)65- Unbounded loops, recursion without depth limit66- Synchronous file/IO on hot paths67- Unmemoized renders, re-instantiated event handlers in JSX68- Loading entire collections to compute a count/exists check6970**Maintainability lens** — will the next engineer cry?71- Functions over ~60 lines or with > 3 levels of nesting72- Boolean flags that should be enums73- Comments explaining *what* (delete) vs *why* (keep)74- Dead code; unreachable branches; commented-out blocks75- Names that lie (`getUser` that creates a user, `validate` that mutates)7677### 3 — Cross-check assumptions7879For each finding, before writing it up:80- Read the surrounding context. Sometimes the "bug" is intentional.81- Search for callers. A function that looks unsafe may only be called from a safe site.82- Check tests. If the behavior is covered, the finding may be by design.8384### 4 — Rank and write8586Order findings by *blast radius*, not by where they appear in the file. A silent data-loss bug on line 412 beats a missing prop type on line 3.8788For each finding, write:8990```91[SEVERITY] file:line — one-line title92 What: the actual problem in 1–2 sentences93 Why it matters: the user-visible impact (data loss, security, perf)94 Fix: the smallest change that resolves it (or a sketch in 3 lines of code)95```9697Don't suggest rewrites unless the file is genuinely beyond repair. Patch-shaped feedback gets fixed; rewrite suggestions get ignored.9899### 5 — Verdict100101End with the one-line verdict. Be decisive. "Looks fine, ship it" is a valid output. So is "Don't merge — issue #2 will corrupt user data on retry."102103## Patterns and anti-patterns104105✅ **Do**:106- Cite `file:line`. Reviews without citations don't get acted on.107- Group findings by file when there are many. Easier to address as a batch.108- Compliment the good parts when they're genuinely good — anchors the trust the rest of the review needs.109110❌ **Don't**:111- Don't pad with nits to look thorough. Three real findings beat thirty fake ones.112- Don't review style if the repo has a formatter. The formatter will do it.113- Don't make confident security claims without tracing the data flow. Hedge if you're not sure: "this *may* be SQL injection — please verify the ORM is parameterizing here."114- Don't suggest a refactor in a bug-fix review. Note it separately.115116## Example invocation117118> User: "Review this PR for the new password reset endpoint." [pastes diff]1191201. Scope: a diff review, security-sensitive, ~80 lines across 3 files.1212. Read with correctness + security lenses prioritized.1223. Findings:123 - **[CRITICAL]** `src/auth/reset.ts:42` — token comparison uses `===`, not `crypto.timingSafeEqual`. Timing-attack vulnerable. Use `crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b))`.124 - **[HIGH]** `src/auth/reset.ts:67` — no rate limit on the request endpoint. Attacker can enumerate emails. Add the existing `rateLimit('auth.reset', { max: 5, window: '15m' })` middleware.125 - **[MED]** `src/auth/reset.ts:88` — error message reveals whether the email exists. Return the same response for "sent" and "not found".126 - **[NOTE]** Token TTL is hard-coded to 1 hour. Consider extracting to `config/auth.ts` so it's tunable.1274. Verdict: blocks merge — fix the timing-safe compare and the rate limit. Other items can land in a follow-up.128129## See also130131- `security-sentinel` — when the review is purely security-focused (OWASP sweep)132- `refactor-master` — to actually apply the structural fixes the audit suggests133- `test-architect` — to add coverage for the edge cases the audit found