Guide · AI-generated code

Reviewing AI-generated code: eight checks before you launch

AI writes code that reads well. That is exactly why it needs a review: fluent code gets skimmed, and someone who skims stops seeing the one line that decides whether a stranger can change a price in your shop. This page is the checklist I work through in a review, in the order that finds expensive mistakes first.

Written by the reviewer at CodeReviewPro · the same checks as in the sample report

01 / Why this review is different

Same rules, different failure modes

Three things about AI-written code change where you look first.

It is written faster than it is read

You can generate a working checkout in an afternoon. Reading that same checkout line by line, with the payment step in mind, is the slower half of the job, and it is normally the half that gets skipped. Code that no one has read is code no one can vouch for.

It sounds confident when it is wrong

Nothing in the output marks the risky line. A charge without error handling looks exactly like a charge with it, until a customer is billed and the confirmation never sends. Reviews have to be driven by the order of operations, not by which code looks suspicious.

The gaps sit where the money is

Authentication, authorization on the server, price and quantity handling, database access and the sequencing around payments are the places where a small mistake becomes an actual loss. That is why those come first here, and styling comes last.

02 / The checks

Eight checks, in this order

Each one is a question you can answer with a search and a read. The commands below assume a JavaScript or TypeScript project; the idea carries over to other stacks.

  1. 01

    Secrets that reach the browser

    Anything a visitor can load, a visitor can read. Keys placed in front-end config, in a client-side environment variable or inside a build that ships to the browser are public the moment you deploy. Look for key-shaped strings in the built assets, not only in the source.

    check the build output, not just the code
    # look for live key shapes in everything the browser downloadsgrep -rniE "sk_(live|test)|secret|api[_-]?key|bearer " build/ public/ dist/
  2. 02

    Values the client is allowed to pick

    If the browser sends the price, the total, the discount or the user id, then the browser decides them. A payment request must be built from data the server looked up itself. The tell is a route that reads something like req.body.price or req.body.total where it should have read the row it just fetched.

  3. 03

    Permission checked on the server

    Hiding an admin button is interface work, not access control. Every route that changes data needs its own check: is this caller logged in, and are they allowed to touch this exact record? The dangerous pattern is a route that checks who you are but never checks what you own, so anyone signed in can read or edit someone else's rows by changing an id.

  4. 04

    Queries built from user input

    String-built SQL is the classic, and it survives because it reads naturally. Parameterised queries and an ORM used properly remove it. The same question applies to file paths, shell commands, redirect targets and any HTML that gets rendered raw.

    two shapes worth grepping for
    db.query("SELECT * FROM products WHERE name LIKE '%" + q + "%'")  // injectiondb.query("SELECT * FROM products WHERE name LIKE $1", ["%" + q + "%"]) // fine# and in the front end:grep -rn "dangerouslySetInnerHTML\|innerHTML\s*=" src/
  5. 05

    The money path, step by step

    Read it as a story: what happens between "customer presses pay" and "customer has a confirmed order". Four questions decide most incidents. Can the same request be replayed twice and charge twice. What happens when the charge succeeds but the next step fails. Is stock checked and reserved before the charge, or only checked. And can two buyers claim the same last item at the same moment.

  6. 06

    Failures that fail silently

    An empty catch block turns a broken payment into a blank page. The checks that matter: is there a try around the calls that can fail, is the error logged with enough context to reconstruct it, does the user see an honest message, and is there a timeout so a hanging call does not hang the request forever.

    the pattern to look for
    try { await charge(card) } catch (e) {}  // customer charged, order unknown
  7. 07

    Dependencies nobody looked at again

    Generated projects pull in a lot, and old packages carry old published vulnerabilities. Check what is actually reachable: run the audit your package manager offers, look at what has had no release in years, and be suspicious of a dependency tree that is far bigger than the app it supports.

    what is installed, and what is known to be wrong
    npm audit --omit=devnpm ls --depth=0
  8. 08

    Deploy and error hygiene

    Debug mode left on, stack traces shown to visitors, an admin route without a login, a database port open to the world, no security headers. These are the findings that cost nothing to fix and are the first thing someone scanning the internet finds.

    what the outside world sees in the headers
    curl -sI https://your-site.example/ | grep -iE "server|content-security|x-content-type|permissions-policy"

If that list looks doable, it is: most of it is reading. What makes it hard is doing it on your own project, where you already know what the code was supposed to do and your eyes skip the parts that match the intention.

03 / What you get from a review

Findings with evidence, not opinions

Every finding in a CodeReviewPro report answers six questions, so you can act on it or hand it to someone who can.

What

The problem in one sentence, in plain language, without jargon that hides the consequence.

Where

The file and the line, quoted, so there is no discussion about which piece of code is meant.

Impact

What it costs you in practice: money, data, access, downtime, or a support ticket you cannot reproduce.

Fix

A suggested fix with a priority and a repair estimate in hours, so you can decide what to do first.

The sample report is a complete report against demonstration code, so you can read the format from beginning to end before deciding anything. It is a made-up shop, not client work, and the page says so.

04 / Questions

Straight answers

Four things people ask before sending code.

Is AI-generated code automatically unsafe?

No. It is ordinary code with the same rules as any other code. What is different is how it is written and how it is read: it is produced in large amounts, it reads fluently, and it is usually shipped without anyone reading it line by line. The mistakes that survive that process are not exotic, they are the boring ones: a key in the front end, a price taken from the browser, a route with no permission check.

Can I run these checks myself?

Yes, most of them. Eight of the checks on this page are grep-and-read work that any developer can do in an afternoon. The part that pays for a second pair of eyes is the money path: the order of operations around charging, writing to the database and sending mail, where a mistake only shows up when a real customer is involved. That is what I read first in a review.

What do you need from me for a review?

A repository, a zip, or the files that matter: routes, database access, payment code, configuration and deployment settings. Read-only access is enough. I do not need your production database, live keys or customer data, and I do not want them.

What happens if you find nothing serious?

Then the report says that, with what was checked and what was left open. A short report with nothing alarming in it is a normal outcome, and it is still useful: it is the difference between assuming the code is fine and knowing what was looked at.

More guides

The same checks, for two other situations

If your app came out of a prompt-driven tool, the vibe-coded app checklist covers the six places those projects break, including the permission rules that are easiest to ship without. And if you are still deciding whether a review is worth paying for, what a code review costs sets out what a scan, a reading and a repair each are, and what the free first look gets you.

05 / Next step

Send your code, get a first look free

Send a repository, a zip or the files that matter, and you get the first findings for free: up to three, if I identify them, with file, line and evidence. If nothing serious turns up, you get that answer instead. A full review is a fixed price: Quick check $299 or Deep check $799, with repairs after the report at $120 per hour if you want them done. The first two clients pay $149 instead of $299.

free first look · up to 3 findings · no subscription, no retainer

Send me your code Read the sample report

Email works too: . Please do not send passwords, live keys or customer data.