Skip to content
Back to skills

3034 Code Review Rules 1431a9b0

ASecurity

Opinionated code review checklist with 50+ actionable rules for security, performance, readability, testing, and error handling

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
code-qualitypythonrustgoshellsqltestingdebuggingrefactoringcode-reviewgit

Works with

  • cursor
  • cli
  • api

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 3034-code-review-rules_1431a9b0 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 3034 Code Review Rules 1431a9b0?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 3034 Code Review Rules 1431a9b0
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-3034-code-review-rules-1431a9b0/badge)](https://www.skillsdirectory.com/skills/tools-only-3034-code-review-rules-1431a9b0)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
---
name: engineering-code-review-rules
description: Opinionated code review checklist with 50+ actionable rules for security, performance, readability, testing, and error handling
---


# Code Review Rules

**Scope**: Security, performance, readability, testing, error handling, architecture review rules
**Lines**: ~300
**Last Updated**: 2026-02-02

## When to Use This Skill

Activate this skill when:
- Reviewing pull requests or code changes
- Writing code that will be reviewed by others
- Setting up automated code review tooling
- Establishing team code review standards
- Auditing existing code for quality issues
- Onboarding engineers to review expectations

## Core Concepts

### Security Rules

**SEC-01: No secrets in source code**
Secrets belong in environment variables, vaults, or secret managers. Never in code, configs checked into git, or comments.

```python
# BAD
API_KEY = "[REDACTED]"
db_url = "postgres://admin:password@prod-db:5432/app"

# GOOD
API_KEY = os.environ["API_KEY"]
db_url = os.environ["DATABASE_URL"]
```

**SEC-02: Parameterize all queries**
Never interpolate user input into SQL, LDAP, or shell commands.

```python
# BAD
cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")

# GOOD
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
```

**SEC-03: Escape all rendered output**
Every user-supplied value rendered in HTML, JSON, or logs must be escaped for its context.

**SEC-04: Validate and sanitize all input at the boundary**
Reject unexpected types, lengths, and characters before they enter your system. Allowlists beat denylists.

**SEC-05: Enforce authentication before authorization**
Every protected endpoint must verify identity, then check permissions. Never assume upstream middleware handled it.

**SEC-06: Use constant-time comparison for secrets**
String equality on tokens or passwords leaks timing information. Use `hmac.compare_digest` or equivalent.

**SEC-07: Set security headers**
`Content-Security-Policy`, `X-Content-Type-Options: nosniff`, `Strict-Transport-Security`. Missing headers are findings.

**SEC-08: Avoid deserialization of untrusted data**
`pickle.loads`, `yaml.load` (without SafeLoader), `eval`, `unserialize` on user data is remote code execution.

**SEC-09: Enforce least privilege on service accounts**
Database users should have only the permissions they need. Read-only services get read-only credentials.

**SEC-10: Log security events, never secrets**
Log authentication failures, permission denials, input validation failures. Never log passwords, tokens, PII.

**SEC-11: Pin dependencies and audit for CVEs**
Use lockfiles. Run `npm audit`, `pip-audit`, `cargo audit` in CI. Block merges on critical CVEs.

---

### Performance Rules

**PERF-01: Eliminate N+1 queries**
If you fetch a list then query per item, you have an N+1. Use JOINs, eager loading, or batch fetches.

```python
# BAD: N+1
for order in orders:
    items = db.query(Item).filter(Item.order_id == order.id).all()

# GOOD: eager load
orders = db.query(Order).options(joinedload(Order.items)).all()
```

**PERF-02: Bound all queries**
Every query against user-controlled data must have a `LIMIT`. Unbounded `SELECT *` is a production incident waiting to happen.

**PERF-03: Add indexes for query patterns**
If you query by a column, it needs an index. Check `EXPLAIN ANALYZE` output. Missing indexes on foreign keys is common.

**PERF-04: Avoid unnecessary allocations in hot paths**
Pre-allocate collections when size is known. Reuse buffers. Avoid creating objects in tight loops.

**PERF-05: Use pagination, not full collection returns**
APIs that return unbounded lists will eventually crash clients or servers. Cursor-based pagination over offset.

**PERF-06: Cache expensive computations**
If a computation is repeated with the same inputs, cache it. But set TTLs and invalidation strategies upfront.

**PERF-07: Avoid synchronous I/O in async contexts**
Blocking calls in async code starve the event loop. Use async drivers or offload to thread pools.

**PERF-08: Profile before optimizing**
Guessing at bottlenecks is wrong more often than right. Measure first with profiling tools.

---

### Readability Rules

**READ-01: Name things for what they represent, not how they work**
`usersByEmail` not `hashMap`. `retryWithBackoff` not `loopAndSleep`.

**READ-02: Functions should do one thing**
If you need "and" to describe what a function does, split it. Aim for under 30 lines per function.

**READ-03: Limit nesting to 3 levels**
Deep nesting kills readability. Use early returns, extract functions, or invert conditions.

```python
# BAD
def process(data):
    if data:
        if data.valid:
            if data.ready:
                return handle(data)

# GOOD
def process(data):
    if not data:
        return None
    if not data.valid:
        return None
    if not data.ready:
        return None
    return handle(data)
```

**READ-04: No magic numbers or strings**
Extract constants with descriptive names. `MAX_RETRY_ATTEMPTS = 3` not bare `3`.

**READ-05: Delete dead code**
Commented-out code, unreachable branches, unused imports, unused variables. Delete them. Git remembers.

**READ-06: Consistent code style**
Use formatters (prettier, black, rustfmt). Style debates in code review waste everyone's time.

**READ-07: Comments explain why, not what**
If code needs a comment to explain what it does, rewrite the code. Comments should explain non-obvious reasoning.

```python
# BAD
# increment counter by 1
counter += 1

# GOOD
# Rate limit resets after 60s, but we add 1s buffer for clock skew
reset_time = rate_limit_reset + 61
```

**READ-08: Group related code, separate unrelated code**
Functions that work together should be near each other. Blank lines separate logical blocks.

**READ-09: Prefer explicit over clever**
Clever one-liners that take 30 seconds to parse cost more than 3 clear lines. Optimize for reading.

**READ-10: Boolean parameters are a code smell**
`render(template, compact=True)` is unclear at the call site. Use enums, separate functions, or configuration objects.

**READ-11: Avoid abbreviations unless universally understood**
`ctx`, `req`, `res`, `err` are fine. `usrAccMgr`, `procHndlr`, `tmpBuf` are not.

---

### Testing Rules

**TEST-01: Tests must be independent**
No test should depend on another test's state or execution order. Each test sets up its own state and tears it down.

**TEST-02: Assert specific values, not truthiness**
`assertEqual(result, 42)` not `assertTrue(result)`. Weak assertions pass when they should fail.

**TEST-03: Test edge cases explicitly**
Empty inputs, null values, boundary values, maximum lengths, unicode, concurrent access. Name the test after the edge case.

**TEST-04: No flaky tests**
A test that fails intermittently is worse than no test. Fix it, quarantine it, or delete it. Never ignore it.

**TEST-05: One assertion per logical concept**
Multiple assertions are fine if they verify one concept. Testing unrelated things in one test obscures failures.

**TEST-06: Test behavior, not implementation**
Tests that break when you refactor internals are coupled to implementation. Test the public contract.

```python
# BAD: tests implementation
assert mock_db.query.call_count == 3

# GOOD: tests behavior
assert len(result.items) == 3
assert result.items[0].name == "expected"
```

**TEST-07: Use factories, not fixtures with shared mutable state**
Shared fixtures create hidden coupling between tests. Factories produce fresh, customizable test data.

**TEST-08: Integration tests should test integration**
If your integration test mocks the thing it integrates with, it is a unit test with extra steps.

**TEST-09: Name tests to describe the scenario and expected outcome**
`test_expired_token_returns_401` not `test_auth` or `test_case_7`.

---

### Error Handling Rules

**ERR-01: Never swallow errors silently**

```python
# BAD
try:
    process(data)
except Exception:
    pass

# GOOD
try:
    process(data)
except ProcessingError as e:
    logger.warning("Processing failed for %s: %s", data.id, e)
    metrics.increment("processing_failures")
```

**ERR-02: Catch specific exceptions**
Broad `catch (Exception)` hides bugs. Catch the specific errors you can handle. Let unexpected errors propagate.

**ERR-03: Clean up resources on error**
Use `try/finally`, context managers, `defer`, or RAII. Resource leaks under error conditions are common.

**ERR-04: Error messages must be actionable**
"Error" is useless. "Failed to connect to database at db.example.com:5432: connection refused" is actionable.

**ERR-05: Do not use exceptions for control flow**
Exceptions are for exceptional conditions. Expected outcomes (user not found, validation failure) should use return values.

**ERR-06: Wrap errors with context when re-raising**
Add context at each layer so the final error message tells the full story.

```python
# BAD
raise

# GOOD
raise OrderProcessingError(f"Failed to process order {order_id}") from e
```

**ERR-07: Validate early, fail fast**
Check preconditions at function entry. The deeper an invalid state travels, the harder it is to debug.

**ERR-08: Define error types for your domain**
`InsufficientBalanceError` is better than `ValueError("not enough money")`. Custom errors enable precise handling.

**ERR-09: Handle partial failures in batch operations**
When processing a list, decide upfront: fail the whole batch, or collect errors and report? Document which.

---

### Architecture Rules

**ARCH-01: Dependencies point inward**
Business logic must not depend on infrastructure. The database adapter depends on the domain, never the reverse.

**ARCH-02: No circular dependencies**
If A depends on B and B depends on A, they are one module or the abstraction is wrong. Extract an interface.

**ARCH-03: Single responsibility at every level**
Functions, classes, modules, and services should each have one reason to change.

**ARCH-04: Prefer composition over inheritance**
Inheritance creates rigid hierarchies. Composition with interfaces allows flexible assembly.

**ARCH-05: Abstract at the right level**
Premature abstraction is as costly as no abstraction. Extract when you see the third instance of a pattern, not the first.

**ARCH-06: API boundaries are contracts**
Changing a public API breaks consumers. Design APIs deliberately. Use versioning. Deprecate before removing.

**ARCH-07: Keep shared mutable state minimal**
Every piece of shared mutable state is a potential race condition and a coupling point. Prefer immutable data and message passing.

---

## Anti-patterns

- **Rubber stamp reviews**: Approving without reading. If you cannot describe what changed, you did not review it.
- **Style nitpicking over substance**: Formatters handle style. Reviewers handle logic, security, and design.
- **Blocking on preferences**: "I would have done it differently" is not a blocking comment unless the approach has concrete downsides.
- **Review scope creep**: Review the diff. Refactoring adjacent code belongs in a separate PR.
- **Skipping tests in review**: Tests are code. Review them with the same rigor as production code.

---

## Checklists

### Quick Review Checklist
- [ ] No secrets or credentials in the diff
- [ ] All user input is validated and sanitized
- [ ] Queries are parameterized and bounded
- [ ] Error paths are handled, not swallowed
- [ ] Tests cover the new behavior and edge cases
- [ ] No N+1 queries or unbounded allocations
- [ ] Function and variable names are clear
- [ ] No dead code, no commented-out code
- [ ] Public API changes are intentional and documented

### Deep Review Checklist
- [ ] All items from Quick Review
- [ ] Authentication and authorization are enforced
- [ ] Resource cleanup happens on all paths (success and error)
- [ ] Concurrency is handled correctly (locks, atomics, message passing)
- [ ] Database migrations are backward-compatible
- [ ] Logging is sufficient for debugging without leaking PII
- [ ] Performance implications considered for hot paths
- [ ] Dependency changes are justified and audited

---

## Related Skills

- `code-quality.md` -- General code quality patterns
- `test-driven-development.md` -- TDD workflow
- `refactoring-patterns.md` -- Safe refactoring techniques
- `code-review.md` -- Code review process and culture

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.