Skip to main content
← Back to Hire

This is a sample deliverable. It shows the format and depth of a $200 code review. The codebase and findings are illustrative, based on common patterns I encounter.

📋
Free Code Review Checklist

A printable 1-page checklist covering security, performance, testing, and more.

Download PDF

Code Review Report

Project: acme-api • Reviewed: March 2026 • Reviewer: Owen Devereaux

Executive Summary

I reviewed approximately 3,200 lines of TypeScript across 47 files in the acme-api repository, focusing on security, performance, and maintainability.

Overall assessment: The codebase is functional but has several security vulnerabilities that should be addressed before production deployment. The architecture is reasonable, though there are opportunities to reduce duplication and improve test reliability.

1
Critical
2
High
3
Medium
2
Low

Priority Actions

  1. Fix SQL injection vulnerability (SEC-001) — This is exploitable and should be patched immediately.
  2. Add rate limiting to auth endpoints (SEC-002) — Prevents brute force attacks.
  3. Optimize N+1 queries (PERF-001) — Will significantly improve response times at scale.

Findings Summary

IDSeverityCategoryTitle
SEC-001CriticalSecuritySQL Injection vulnerability in user search
SEC-002HighSecurityMissing rate limiting on authentication endpoints
PERF-001HighPerformanceN+1 query pattern in order listing
MAINT-001MediumMaintainabilityDuplicated validation logic across handlers
MAINT-002MediumMaintainabilityMagic numbers in business logic
ERR-001MediumError HandlingSwallowed exceptions in async handlers
TEST-001LowTestingIntegration tests share database state
DOC-001LowDocumentationMissing JSDoc on public API functions

Detailed Findings

SQL Injection vulnerability in user search

SEC-001

Location: src/services/userService.ts:47

User input is directly interpolated into SQL query without parameterization. An attacker could extract or modify database contents.

Recommendation: Use parameterized queries or an ORM query builder.

Before
// ❌ Vulnerable to SQL injection
const query = `SELECT * FROM users WHERE name LIKE '%${searchTerm}%'`;
const results = await db.raw(query);
After
// ✅ Parameterized query
const results = await db('users')
  .where('name', 'like', `%${searchTerm}%`);

Missing rate limiting on authentication endpoints

SEC-002

Location: src/routes/auth.ts

Login and password reset endpoints have no rate limiting, enabling brute force attacks.

Recommendation: Add rate limiting middleware (e.g., express-rate-limit) with appropriate thresholds.

Before
// ❌ No rate limiting
router.post('/login', loginHandler);
After
// ✅ With rate limiting
const loginLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 5, // 5 attempts per window
  message: 'Too many login attempts'
});
router.post('/login', loginLimiter, loginHandler);

N+1 query pattern in order listing

PERF-001

Location: src/services/orderService.ts:23

Each order triggers a separate database query for customer data. With 100 orders, this results in 101 queries.

Recommendation: Use eager loading or batch the customer lookup.

Before
// ❌ N+1 queries
const orders = await Order.findAll();
for (const order of orders) {
  order.customer = await Customer.findById(order.customerId);
}
After
// ✅ Single query with join
const orders = await Order.findAll({
  include: [{ model: Customer, as: 'customer' }]
});

Duplicated validation logic across handlers

MAINT-001

Location: src/handlers/*.ts

Email and phone validation is copy-pasted across 7 different files. Changes require updates in multiple places.

Recommendation: Extract to a shared validation utility or use a schema validation library like Zod.

Magic numbers in business logic

MAINT-002

Location: src/services/pricingService.ts

Discount percentages and thresholds are hardcoded (0.15, 1000, etc.) without explanation.

Recommendation: Extract to named constants or configuration.

Before
// ❌ Magic numbers
if (total > 1000) {
  discount = total * 0.15;
}
After
// ✅ Named constants
const BULK_DISCOUNT_THRESHOLD = 1000;
const BULK_DISCOUNT_RATE = 0.15;

if (total > BULK_DISCOUNT_THRESHOLD) {
  discount = total * BULK_DISCOUNT_RATE;
}

Swallowed exceptions in async handlers

ERR-001

Location: src/handlers/webhookHandler.ts:34

Catch block logs error but doesn't propagate it. Failures appear successful to callers.

Recommendation: Re-throw or return error response after logging.

Integration tests share database state

TEST-001

Location: tests/integration/*.test.ts

Tests don't reset database between runs, causing flaky failures when run in different orders.

Recommendation: Add beforeEach hook to reset test database or use transactions.

Missing JSDoc on public API functions

DOC-001

Location: src/api/*.ts

Public functions lack documentation for parameters and return values.

Recommendation: Add JSDoc comments, especially for functions used by other modules.

Get a review like this for your codebase

$200 flat rate. Delivered in 48 hours. No surprises.

Request a Code Review