Reviewing AI-generated code requires more than checking whether it compiles or passes the tests created by the same AI. A convincing implementation can still misunderstand the requirement, weaken authorization, mishandle unusual inputs, duplicate existing logic, or introduce failures that appear only under real production conditions.
A reliable AI-generated code review separates implementation from verification. The reviewer starts with the task requirements, inspects the actual diff, follows data through the system, challenges the tests, runs independent checks, and requires evidence before approving the pull request.
What you will build
A repeatable review workflow for finding hidden logic, security, authorization, data, testing, and maintainability problems in AI-generated code.
Best for
Developers, reviewers, technical founders, engineering teams, and anyone approving pull requests created partly or entirely by an AI coding assistant.
Why AI-generated code needs a different review process
AI-generated code often looks cleaner than its underlying reasoning deserves. It may use appropriate names, familiar patterns, comments, tests, and confident explanations while still implementing the wrong behavior.
The main risk is not that every generated line is poor. The risk is that polished output can lower the reviewer’s skepticism.
Common causes of false confidence include:
- The AI writes both the implementation and the tests.
- The pull request summary describes intended behavior rather than actual behavior.
- The change follows a familiar pattern that does not fit the current requirement.
- Only the successful path is demonstrated.
- Automated checks validate syntax but not business rules.
- The reviewer reads the AI explanation before inspecting the diff.
- A large change contains many individually reasonable edits that interact incorrectly.
The reviewer should treat the AI as an unfamiliar contributor that can work quickly but does not own the product decision, security decision, or final approval.
What counts as a hidden bug?
A hidden bug is a defect that is not obvious from a quick reading or a successful demonstration. It may remain invisible until the system receives unusual data, multiple requests arrive together, a user lacks permission, an external service fails, or the code runs in a different environment.
Hidden bugs usually live in the difference between:
- What the task requested and what the code actually does.
- What the test proves and what the reviewer assumes it proves.
- What happens in a demonstration and what happens in production.
- What a normal user can do and what an unauthorized user can attempt.
- What happens once and what happens under retries or concurrency.
- What the new code assumes and what the existing system guarantees.
Ten hidden bug categories to inspect
1. Requirement drift
The implementation solves a nearby problem instead of the approved problem. This often happens when the task uses broad language such as “improve,” “support,” “optimize,” or “make flexible.”
Look for:
- Acceptance criteria that are only partially implemented.
- New behavior that was not requested.
- Changed defaults or permissions.
- Missing out-of-scope boundaries.
- Assumptions that were never approved.
2. Boundary and empty-state failures
Generated code commonly handles representative values while overlooking minimums, maximums, missing values, empty collections, duplicates, malformed input, and unusual character sets.
- Empty strings and whitespace-only values.
- Zero and negative numbers.
- Values exactly at the permitted limit.
- Values just above or below the limit.
- Missing properties and null values.
- Empty arrays or result sets.
- Duplicate requests or repeated submissions.
- Unicode, long text, and unexpected encodings.
3. Authorization gaps
A user interface can hide an action without actually protecting it. Authorization must be enforced at the trusted server-side boundary, not only in a button, route guard, or client-side condition.
Review whether the code checks:
- Who the current user is.
- Whether the user owns or may access the specific resource.
- Whether the requested action is permitted for that role.
- Whether an identifier can be changed to access another user’s data.
- Whether bulk actions repeat the same authorization check.
- Whether background jobs preserve the original authorization boundary.
4. Validation in the wrong layer
Validation may exist in the browser but not in the API, service, job, database path, or import process. An attacker, integration, outdated client, or internal script may bypass the visible interface.
Follow every input from its entry point to the place where it is trusted, stored, rendered, or used in a command.
5. Incorrect data and transaction behavior
A sequence of individually correct database operations can leave inconsistent data when one operation fails halfway through.
- Should multiple writes be atomic?
- Can a partial operation remain after an exception?
- Can two requests update the same record incorrectly?
- Does the code check whether the record changed after it was read?
- Can a retry create a duplicate?
- Are deletes, updates, and related records handled consistently?
6. Concurrency and idempotency bugs
Code that works during one manual test may fail when the same action runs twice, two users act at once, a queue retries a job, or an external service returns late.
Ask:
- What happens if the request is submitted twice?
- Can two workers process the same item?
- Can a payment, email, notification, or record be created twice?
- Is an operation safe to retry?
- Does the code depend on reading a value that may immediately change?
7. Error handling that hides the real failure
Broad exception handling may convert every failure into a generic response, continue after an invalid state, or log too little information to diagnose the incident.
- Exceptions caught and ignored.
- Generic success returned after a partial failure.
- Fallback behavior that silently changes the result.
- Sensitive data written to logs.
- Error messages exposing internal implementation details.
- Retries without limits or backoff.
- Missing cleanup after a failure.
8. Configuration and environment assumptions
The generated implementation may work in the local environment while relying on unavailable services, operating-system behavior, environment variables, file paths, time zones, locale settings, or database features.
- Hard-coded paths, domains, ports, or credentials.
- Assumed environment variables without validation.
- Local-only dependencies.
- Case-sensitive file-name differences.
- Time-zone and date-boundary problems.
- Production configuration modified unnecessarily.
9. Dependency and supply-chain changes
An AI may add a package to avoid writing a small amount of code. That package can increase maintenance, licensing, security, bundle-size, and update risk.
For each new dependency, ask:
- Is it necessary?
- Is equivalent functionality already present?
- Is the package actively maintained?
- What permissions or transitive dependencies does it introduce?
- Can a smaller internal implementation solve the requirement?
- Was adding the dependency explicitly approved?
10. Tests that create false confidence
A generated test may pass because it repeats the implementation’s assumptions, mocks the important behavior, checks only that a function was called, or asserts a value that the test itself constructed.
The strongest question is:
Would this test fail if the feature were removed or the suspected bug were introduced?
The eight-stage AI-generated code review workflow
| Stage | Reviewer action | Main risk addressed |
|---|---|---|
| 1. Reconstruct intent | Read requirements before the diff | Requirement drift |
| 2. Inspect scope | Map every changed file to the task | Unrelated or excessive changes |
| 3. Follow behavior | Trace inputs, decisions, side effects, and outputs | Logic and data-flow defects |
| 4. Challenge trust boundaries | Review validation, authorization, and sensitive operations | Security and access-control failures |
| 5. Challenge tests | Verify that tests prove observable behavior | False confidence |
| 6. Run independent checks | Execute tests, static analysis, build, and manual cases | Unsupported completion claims |
| 7. Review maintainability | Compare with repository conventions | Long-term maintenance cost |
| 8. Record the decision | Document findings, evidence, and remaining risk | Unclear approval responsibility |
Stage 1: Reconstruct the intended behavior
Do not begin with the AI-written summary. Start with the original issue, task brief, acceptance criteria, design decision, or bug report.
Create a simple requirement matrix:
| Requirement | Expected evidence | Status |
|---|---|---|
| Authorized user can perform the action | Implementation and passing permission test | Pending review |
| Unauthorized user is rejected | Server-side check and negative test | Pending review |
| Invalid input is rejected | Validation rule and boundary tests | Pending review |
| Existing behavior remains unchanged | Regression tests | Pending review |
This prevents an impressive implementation from distracting the reviewer from an unmet requirement.
For a complete task-definition process, begin with the AI Coding Workflow: From Task Brief to Tested Pull Request.
Stage 2: Review the scope before reviewing individual lines
List every file that was created, edited, renamed, or deleted. Then require a task-related reason for each one.
High-risk scope signals include:
- Lockfiles changed without an approved dependency.
- Authentication or authorization files changed for an unrelated feature.
- CI, deployment, or infrastructure configuration modified.
- Database migrations added unexpectedly.
- Large formatting changes mixed with behavioral changes.
- Shared utilities modified to solve a local problem.
- Generated or vendor files committed unnecessarily.
- Tests deleted or weakened.
Scope review prompt
Review this pull request only for scope.
Inputs:
- original task
- approved implementation plan
- changed file list
- diff summary
For every changed file:
1. Explain why the file must change.
2. Identify whether the change was predicted by the plan.
3. Flag unrelated formatting or refactoring.
4. Flag dependency, CI, permission, migration, or configuration changes.
5. Identify files that should have changed but did not.
6. Classify each concern as blocking, important, or optional.
Do not review code style yet.
Stage 3: Follow the behavior through the system
Read the code as a sequence of states and decisions rather than a collection of functions.
- Where does the input originate?
- Who controls the input?
- Where is it parsed and validated?
- Which authorization decision applies?
- Which business rules transform it?
- Which records, files, services, or messages are affected?
- What output or response is returned?
- What happens when any step fails?
Do not review only the new function. Follow the call chain into existing services, database operations, background jobs, external APIs, templates, and error handlers.
Data-flow review worksheet
DATA FLOW REVIEW
Input source:
Input controlled by:
Initial validation:
Normalization:
Authorization check:
Business-rule checks:
Database reads:
Database writes:
External services:
Files or commands:
Output encoding:
Logs created:
Errors returned:
Retry behavior:
Cleanup behavior:
Sensitive data involved:
Unexpected states:
Stage 4: Inspect trust boundaries and dangerous assumptions
A trust boundary exists wherever information moves from a less trusted source to a more trusted operation. Examples include requests entering an API, file uploads reaching storage, user input entering a database query, and job payloads triggering privileged actions.
At each boundary, review:
- Authentication.
- Authorization.
- Input validation.
- Output encoding.
- Data ownership.
- Rate and size limits.
- File and path handling.
- Command construction.
- Secret handling.
- Error and audit logging.
Example: visible permission check, missing resource authorization
// Looks protected because a user must be logged in.
async function renameReport(request, response) {
const user = request.user;
const reportId = request.params.id;
if (!user) {
return response.status(401).send('Unauthorized');
}
const report = await reports.findById(reportId);
report.title = request.body.title;
await report.save();
return response.json(report);
}
The code authenticates the user but does not verify that the user owns the report or has permission to rename it. A logged-in user may be able to change another user’s report by modifying the identifier.
The reviewer should look for an existing authorization service or ownership check rather than inventing a new permission rule during review.
Stage 5: Review the tests as critically as the implementation
Tests are evidence only when they are independent enough to catch incorrect behavior.
Map each test to a requirement
| Required behavior | Positive test | Negative or boundary test |
|---|---|---|
| Authorized rename succeeds | Owner receives updated report | Unrelated fields remain unchanged |
| Unauthorized rename fails | Approved role may rename | Different owner receives rejection |
| Title validation applies | Valid title is accepted | Empty, short, long, and malformed titles fail |
| Operation remains consistent | Single request succeeds | Duplicate or concurrent requests remain safe |
Look for weak test patterns
- Asserting only that a function was called.
- Mocking the database, authorization, or external boundary being tested.
- Recreating production logic inside the expected value.
- Testing implementation details instead of observable results.
- Using only one representative input.
- Skipping failure and permission cases.
- Replacing a strong existing test with a weaker generated test.
- Snapshots accepted without inspecting the changed output.
- Tests that pass even when the feature code is removed.
Independent test review prompt
Review these tests independently from the implementation summary.
For each test:
- identify the requirement it proves
- state the observable behavior being tested
- explain whether the test would fail if the feature were removed
- identify important behavior that has been mocked
- identify duplicated production logic
- identify missing permission, validation, failure, and boundary cases
- flag assertions that are too weak
- propose the smallest missing tests needed for confidence
Do not assume passing tests mean the implementation is correct.
Stage 6: Run independent validation
Do not rely only on commands listed in the AI-generated pull request description. Run or verify the relevant commands independently against the final commit.
- Focused tests for the changed feature.
- Relevant integration tests.
- Full regression suite when risk justifies it.
- Lint and formatting checks.
- Static analysis and type checking.
- Application build.
- Dependency and vulnerability checks.
- Manual tests based on the acceptance criteria.
Record the exact command, result, environment, and commit. A result from an earlier version of the branch is not evidence for the final diff.
Adversarial manual test ideas
- Repeat the same action twice.
- Use another user’s resource identifier.
- Remove optional fields.
- Send malformed or oversized values.
- Interrupt an external dependency.
- Force a database or network failure.
- Run the action concurrently.
- Change the system time zone or locale.
- Use an older client or missing configuration.
- Retry a partially completed operation.
Stage 7: Review maintainability and repository fit
Code can be functionally correct and still be the wrong implementation for the repository.
Compare the change with nearby approved code:
- Does it use the existing service, validation, and authorization layers?
- Does it introduce a second way to perform an existing task?
- Are names consistent with the domain?
- Is complexity proportional to the requirement?
- Are comments explaining decisions rather than obvious syntax?
- Has reusable code been placed at the correct level?
- Will another developer understand the failure behavior?
- Does the change make future testing easier or harder?
Reject unnecessary abstractions added only because the AI predicts that they may be useful later.
Stage 8: Record a defensible review decision
A review should end with more than “looks good.” Record what was checked, which evidence supports approval, and which risks remain.
| Decision | Meaning |
|---|---|
| Approve | Requirements, evidence, security, and maintainability are acceptable |
| Approve with follow-up | Non-blocking improvement is documented separately |
| Request changes | A correctness, security, testing, or scope problem must be fixed |
| Escalate | A product, architecture, privacy, legal, or security decision exceeds the reviewer’s authority |
Do not approve code merely because no obvious defect was found. Approval should be based on positive evidence that the required behavior and important failure cases were examined.
Security review checklist for AI-generated code
- Authentication is required at the correct boundary.
- Authorization applies to the specific resource and action.
- Untrusted input is validated on the trusted side.
- Output is encoded for its destination.
- Database access avoids unsafe query construction.
- File paths and uploads are restricted appropriately.
- Commands do not include untrusted text unsafely.
- Secrets and tokens are not committed or logged.
- Sensitive data is minimized in errors and telemetry.
- Cryptographic functions use approved existing libraries.
- Retries and duplicate operations cannot create harmful side effects.
- Dependencies and configuration changes were approved.
- Security checks cover the final commit.
For projects involving personal or confidential information, combine this review with the AI Privacy Review Checklist for Automation Projects.
Risk-based review depth
Not every change needs the same level of review. Scale the process according to possible impact.
| Risk level | Examples | Expected review |
|---|---|---|
| Low | Copy changes, internal documentation, isolated formatting | Scope check, preview, basic validation |
| Moderate | New interface behavior, report logic, internal automation | Requirement mapping, focused tests, manual edge cases |
| High | Authentication, permissions, payments, personal data, migrations | Independent reviewer, security analysis, broad tests, rollback plan |
| Critical | Production infrastructure, cryptography, irreversible data operations | Specialist review, staged release, explicit approval and monitoring |
Copyable AI code review prompts
Requirement compliance review
Compare this code change with the original task and acceptance criteria.
Create a table with:
- requirement
- implementation evidence
- test evidence
- missing behavior
- confidence level
Do not infer that a requirement is complete from the pull request summary. Cite the actual changed files and tests.
Hidden bug review
Review this diff for hidden bugs.
Focus on:
- empty and boundary values
- null and missing data
- authorization and ownership
- duplicate requests
- retries and concurrency
- partial database updates
- external service failures
- error handling and cleanup
- time zones and locale assumptions
- configuration differences
- backwards compatibility
- tests that create false confidence
For every finding:
1. Describe the failure scenario.
2. Cite the relevant file and code.
3. Explain the user or system impact.
4. Classify severity.
5. Propose a focused test that would expose the problem.
Security-focused review
Perform a security-focused review of this change.
Trace untrusted input to sensitive operations.
Check:
- authentication
- resource-level authorization
- input validation
- output encoding
- database queries
- file and path handling
- command execution
- secret exposure
- sensitive logging
- dependency changes
- permission changes
- unsafe defaults
- failure and retry behavior
Do not report a theoretical issue without explaining a realistic attack or failure path.
Test quality review
Evaluate whether these tests provide real confidence.
For each test, determine:
- which requirement it proves
- whether it tests observable behavior
- whether it would fail if the implementation were removed
- whether important behavior is mocked
- whether expected values duplicate production logic
- which negative and boundary cases are missing
Return:
- strong tests
- weak tests
- missing tests
- misleading tests
- recommended independent manual checks
Complete human review checklist
Intent and scope
- The original task and acceptance criteria were reviewed.
- Every changed file has a clear task-related purpose.
- Unrelated refactoring and formatting were excluded.
- New dependencies, migrations, configuration, and permissions were identified.
- The implementation does not expand the approved product scope.
Behavior and data
- The successful path satisfies the requirement.
- Empty, invalid, missing, duplicate, and boundary values were tested.
- Partial failures leave the system in a valid state.
- Retries and concurrent actions are safe.
- Data ownership and related records remain correct.
- Backwards compatibility was considered.
Security and privacy
- Authentication is enforced.
- Authorization is checked for the specific action and resource.
- Input is validated at the trusted boundary.
- Output is encoded appropriately.
- Secrets and personal information are not exposed.
- Logs and errors contain enough diagnostic information without leaking sensitive data.
- Dependencies and privileged configuration changes are justified.
Tests and evidence
- Tests map to the acceptance criteria.
- Negative, permission, and boundary cases exist.
- Tests do not merely repeat the implementation.
- Important behavior is not mocked away.
- Focused and relevant regression tests pass.
- Lint, type checks, static analysis, and builds pass where applicable.
- Evidence applies to the final commit.
- Skipped checks are documented.
Maintainability and release
- The change follows existing repository conventions.
- The implementation is no more complex than necessary.
- Names and responsibilities are understandable.
- The pull request explains risks and review focus.
- A rollback or disable path exists for risky changes.
- Relevant production behavior can be monitored.
- A qualified human owns the final decision.
AI-generated code review report template
AI-GENERATED CODE REVIEW REPORT
Pull request:
Reviewer:
Commit reviewed:
Risk level:
1. REQUIREMENT COVERAGE
Requirement:
Implementation evidence:
Test evidence:
Status:
2. SCOPE REVIEW
Expected files:
Unexpected files:
Dependencies:
Configuration:
Migrations:
Permissions:
Unrelated changes:
3. BEHAVIOR REVIEW
Happy path:
Invalid input:
Empty state:
Boundary values:
Duplicate request:
Concurrency:
Partial failure:
External service failure:
Backwards compatibility:
4. SECURITY REVIEW
Authentication:
Authorization:
Input validation:
Output encoding:
Database access:
File handling:
Command execution:
Secrets:
Sensitive logs:
Dependency risk:
5. TEST REVIEW
Strong tests:
Weak tests:
Missing tests:
Misleading tests:
Manual checks:
Commands verified:
6. FINDINGS
Finding:
Severity:
File:
Failure scenario:
Impact:
Required correction:
Recommended test:
7. FINAL DECISION
[ ] Approve
[ ] Approve with follow-up
[ ] Request changes
[ ] Escalate
Evidence supporting decision:
Remaining risks:
Follow-up owner:
Common review mistakes
Reading the AI summary before the requirements
The summary frames the reviewer’s expectations and may hide missing behavior. Start with the original task.
Reviewing only the changed function
The bug may exist in the caller, authorization layer, database transaction, background job, or error handler. Follow the complete behavior.
Accepting AI-generated tests as independent evidence
The same assumptions may be embedded in both the implementation and the tests. Challenge the tests separately.
Focusing on style before correctness
Formatting and naming comments can create activity while serious logic and authorization problems remain unnoticed. Review risk first.
Using another AI reviewer as the only reviewer
An AI reviewer can surface suspicious areas, but it may share the same blind spots, misunderstand the domain, or accept unsupported assumptions. Human accountability remains necessary.
Approving because the change is small
A one-line permission, query, comparison, or configuration change can carry more risk than a large isolated feature. Review depth should follow impact, not line count.
How to add this review process to your team
- Add acceptance criteria and explicit boundaries to issue templates.
- Create a pull request template requiring validation evidence.
- Add the human review checklist to repository documentation.
- Require an independent reviewer for AI-generated changes.
- Protect sensitive branches with reviews and required checks.
- Use automated static and security analysis as supporting evidence.
- Start with moderate-risk changes and record missed defects.
- Update the checklist when a real bug escapes review.
The checklist should evolve from actual incidents, rejected pull requests, production defects, and repository-specific risks rather than remaining a generic document.
How to measure review quality
- Percentage of AI-generated pull requests requiring major rework.
- Defects discovered during review versus after merge.
- Authorization and validation findings per pull request.
- Percentage of acceptance criteria with direct test evidence.
- Frequency of unrelated scope expansion.
- Post-merge rollback and incident rate.
- Average number of meaningful findings per review.
- Repeated bug categories that should become repository rules.
Do not reward reviewers for approving quickly or producing many comments. Measure whether they identify important problems before those problems reach users.
Frequently asked questions
Should AI-generated code receive more review than human-written code?
Review depth should follow risk, scope, and available evidence. AI-generated code deserves particular attention when the AI also created the plan, implementation, tests, and completion summary because those outputs may share the same assumptions.
Can passing tests prove that AI-generated code is safe?
No single test result proves overall safety. Tests provide evidence for the scenarios they cover. Authorization, data flow, configuration, concurrency, privacy, and production behavior may require additional analysis.
Should the reviewer use an AI assistant?
An AI assistant can help enumerate edge cases, trace a diff, compare code with requirements, and suggest tests. Its findings should be verified against the actual repository and domain behavior.
What is the fastest useful review technique?
Start with three checks: compare the diff with the acceptance criteria, verify authorization for every changed action, and test one invalid or adversarial path that the pull request does not demonstrate.
Who should approve security-sensitive AI-generated code?
A reviewer with the necessary repository, security, and domain knowledge should own the approval. High-impact changes may require specialist or multiple-reviewer approval.
Final takeaway
The safest way to review AI-generated code is to separate confidence from appearance. Clean code, a persuasive summary, and passing generated tests are useful signals, but they are not substitutes for independent verification.
Start with the requirement, control the scope, follow the complete behavior, challenge trust boundaries, examine the tests, run independent checks, and record a defensible human decision.
Related guides
- AI Coding Workflow: From Task Brief to Tested Pull Request
- AI Prompt Evaluation Workflow
- AI Privacy Review Checklist for Automation Projects
- AI Tool Audit Workflow Before Buying Software
- Browse Writoria’s AI Workflow Guides
Official references
- GitHub Docs: Review AI-generated code
- GitHub Docs: About GitHub Copilot code review
- GitHub Docs: Writing tests with GitHub Copilot
- OWASP Secure Code Review Cheat Sheet
- OWASP Secure Coding Practices Checklist
- NIST Secure Software Development Framework