Skip to content
NEXDGE
Start free

How to review AI-generated code before you ship it

A five-point checklist for reviewing Cursor, Copilot and Claude Code output before production: auth, error handling, queries, logic and responses.

5 min readUpdated 29 July 2026
In short

Review AI-generated code by checking five things in order: server-side authorisation on every data endpoint, error and timeout handling on every external call, parameterised database queries, business logic against your actual written rules, and what each API response exposes.

Key takeaways
  • Review AI output in a fixed order, because the highest-severity defects cluster in the first two checks.
  • Authorisation is the highest-yield check: verify ownership is enforced inside the query, not in an if-statement above it.
  • Every external call needs three things the model usually omits: a try/catch, a timeout, and a defined failure state.
  • Business logic can only be reviewed against rules you have written down. The reviewer cannot infer your pricing from your code.
  • Manual application of this checklist takes 15–40 minutes per file, which is why it stops happening under deadline.

AI tools generate code faster than any team can read it. That is the point of them. But generation without a review step is how a critical defect reaches production wearing clean formatting and sensible variable names.

This is the checklist to run before AI-generated code ships. It is ordered deliberately: the first two checks catch the defects that cause incidents, so if you only have five minutes, spend them at the top.

Why does AI-generated code need a different review process?

Traditional review is a senior engineer reading a diff and applying pattern recognition. That works well on human code, because human defects correlate with human signals: rushed naming, a tangled function, a comment that says "temporary".

AI-generated code removes every one of those signals. Naming is consistent, structure is clean, comments are complete. The surrounding hundred lines are genuinely good, which creates a strong impression of quality precisely where the one bad line is hiding. Human reviewers relax exactly where they should not.

1. Authorisation boundaries (highest yield, start here)

For every endpoint that returns or mutates user data, answer one question: if I change an ID in this request to a different user's ID, what comes back?

The safe pattern is to make ownership part of the query rather than a check before it. A separate check can be skipped, reordered, or refactored away; a constraint inside the query cannot be, because removing it changes what the query returns.

Ownership belongs in the query
// Fragile: the guard is separate from the fetch
const doc = await Document.findById(id)
if (doc.userId !== session.userId) return res.status(403).end()

// Durable: a non-owner simply gets no row
const doc = await Document.findOne({ _id: id, userId: session.userId })
if (!doc) return res.status(404).end()

Note the 404 rather than 403 in the second version. Returning 403 confirms the record exists, which hands an attacker a working existence oracle for free.

2. External calls: error, timeout, fallback

Every fetch, axios call, or SDK invocation needs three things. Models produce the first inconsistently and the second and third almost never.

  1. A try/catch, or an explicit response-status check. A non-2xx response is not an exception in most HTTP clients, so await fetch() succeeding tells you nothing about whether it worked.
  2. A timeout. Without one, a hanging upstream service holds your request open until your own platform kills it, and one slow dependency becomes your outage.
  3. A defined failure state in the UI. If the call fails, the interface must say so. A spinner that never resolves is indistinguishable from your product being broken.

3. Query construction

Any query incorporating user input must be parameterised or built through an ORM. String interpolation into SQL is an injection vulnerability regardless of how harmless the input looks in testing, and template literals make it read like clean modern JavaScript, which is exactly why it survives review.

The template literal is the tell
// Vulnerable: reads fine, is not fine
const q = `SELECT * FROM users WHERE email = '${email}'`

// Parameterised
const q = 'SELECT * FROM users WHERE email = $1'
await db.query(q, [email])

This pattern and the rest of the recurring security shapes are covered in more depth in security risks in Cursor and Copilot code.

4. Business logic against written rules

This check is different from the others: it cannot be performed by reading the code alone. Nothing in a pricing function tells you whether 18% is the right rate, whether the discount applies before or after tax, or whether that ordering differs by country.

So write the rule down first, in one or two sentences, and then check the implementation against the sentence. "Discount applies to the pre-tax subtotal. GST is 18%, or 5% on essential goods, calculated after the discount." Now the review is a comparison rather than a guess, and it is the only way to catch a function that computes the wrong number without any defect in the code.

5. Response shape and data exposure

Look at what each endpoint actually returns, not what it is supposed to return. Serialising a whole database row is the default AI pattern and it commonly leaks password hashes, internal flags, soft-delete markers, or other users' identifiers embedded in nested relations. Select fields explicitly; never return a raw model.

How to make this actually happen under deadline

Applied by hand, this checklist takes fifteen to forty minutes per file. That is sustainable for a week and then it quietly stops happening, usually in the sprint before launch, the one where the most code is being generated and the least is being read.

The realistic answer is to automate the five checks so they run in parallel in seconds and return findings graded by severity, and to reserve human judgement for the decisions that genuinely need it. Nexdge runs exactly these five as separate specialists (security, reliability, business logic, performance, and quality) and returns a verified rewrite alongside the findings.

Frequently asked questions

What should I check first in AI-generated code?

Authorisation. For every endpoint returning user data, change an identifier in the request and confirm you get a 404 rather than another user's record. Missing authorisation is the most common critical-severity defect in AI-generated backends.

How long does reviewing AI-generated code take?

Applying a five-point checklist manually takes an experienced engineer roughly 15 to 40 minutes per file. Automated specialist review completes the same checks in about thirty seconds by running them in parallel.

Should I return 403 or 404 when a user requests someone else's record?

Return 404. A 403 confirms the record exists, which gives an attacker a reliable way to enumerate valid identifiers. A 404 reveals nothing about whether the resource is real.

Can automated tools review business logic?

Only if you supply the rules. No reviewer can infer from your code that your tax rate should be 18 percent or that a discount applies pre-tax. Provide the rule in plain language and the implementation can be checked against it.

Does this checklist apply to Copilot and Claude Code as well as Cursor?

Yes. The failure patterns come from how language models are trained rather than from any particular editor, so the same five checks apply to output from Cursor, GitHub Copilot, Claude Code, Bolt, Lovable, and Windsurf.

Sources

  1. Do Users Write More Insecure Code with AI Assistants? (Stanford, 2022)Controlled study finding participants with an AI assistant wrote less secure code while believing it was more secure.
  2. OWASP Top 10The consensus list of the ten most critical web application security risks.
  3. NIST SP 800-218: Secure Software Development FrameworkThe practices most software supply-chain requirements are written against.

Run all five checks in parallel on your next file, in about thirty seconds.

Start free