惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Schneier on Security
A
Arctic Wolf
S
Security Affairs
O
OpenAI News
SecWiki News
SecWiki News
TaoSecurity Blog
TaoSecurity Blog
H
Heimdal Security Blog
T
Threat Research - Cisco Blogs
Hacker News: Ask HN
Hacker News: Ask HN
N
News | PayPal Newsroom
Google Online Security Blog
Google Online Security Blog
C
Cisco Blogs
The Hacker News
The Hacker News
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
C
CXSECURITY Database RSS Feed - CXSecurity.com
P
Privacy International News Feed
V
Vulnerabilities – Threatpost
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
T
Tenable Blog
T
The Exploit Database - CXSecurity.com
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Spread Privacy
Spread Privacy
人人都是产品经理
人人都是产品经理
www.infosecurity-magazine.com
www.infosecurity-magazine.com
V2EX - 技术
V2EX - 技术
L
LINUX DO - 最新话题
The GitHub Blog
The GitHub Blog
博客园 - 三生石上(FineUI控件)
T
The Blog of Author Tim Ferriss
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V
Visual Studio Blog
The Cloudflare Blog
N
News and Events Feed by Topic
量子位
Google DeepMind News
Google DeepMind News
Application and Cybersecurity Blog
Application and Cybersecurity Blog
L
LINUX DO - 热门话题
P
Palo Alto Networks Blog
Stack Overflow Blog
Stack Overflow Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Attack and Defense Labs
Attack and Defense Labs
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Hacker News - Newest:
Hacker News - Newest: "LLM"
Apple Machine Learning Research
Apple Machine Learning Research
The Register - Security
The Register - Security
Microsoft Security Blog
Microsoft Security Blog
Know Your Adversary
Know Your Adversary
Webroot Blog
Webroot Blog

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
AI Code Review: Helpful Assistant Or False Confidence Machine?
Nazar Boyko · 2026-06-02 · via DEV Community

You open a pull request. Thirty seconds later, an AI reviewer drops a comment: "Looks good to me. No issues found."

You feel a tiny chemical reward. Approval. Speed. You're one click closer to merging. The cognitive cost of waiting for a human reviewer just got compressed into half a minute, and the diff you spent two hours wrestling with is now blessed by a system that has read more code than any single engineer alive.

Then a week later, the same code ships a subtle authorization bug to production, and you're staring at an incident channel wondering how that "Looks good to me" survived a real review.

This is the question that follows every AI code reviewer around like a shadow. Is it a helpful assistant - a faster, calmer, more patient version of the senior engineer who used to leave you twelve comments before lunch? Or is it a false confidence machine - a tool that says reassuring things about code it doesn't fully understand, and convinces you to merge anyway?

The honest answer is both, and which one you get depends almost entirely on how you set up the workflow around it. Let's break down the four angles that actually matter - what these reviewers catch well, where they fail on correctness, where they fail on security, where they make things up, and how to design a review process that gets the upside without buying the downside.

What AI Code Review Is Actually Good At

Before we pile on the failure modes, it's worth being fair about what these tools do well - because most teams hire them for the right reasons and then forget what those reasons were.

AI reviewers are excellent at the surface layer of code review. The kind of comments that good engineers stop making out loud because they got tired of writing them but still wish someone would catch:

  • Inconsistent naming inside the same diff. You called it userId in one function and user_id in the next.
  • Style drift. A trailing comma here, a missing one there, a callback where the rest of the file uses async/await.
  • Obvious nullability holes. You destructured response.data.user two lines after a try block that could return undefined.
  • Forgotten error handling. The new endpoint catches the database error but swallows the auth error two lines below.
  • Dead code, unused variables, imports that no longer point at anything.
  • Documentation that contradicts the function it's documenting because the signature changed and the JSDoc didn't.

These comments aren't glamorous, but they used to consume real review bandwidth from senior engineers. Pushing them onto a tool that doesn't get tired, doesn't get cranky, and doesn't write "as I've mentioned in the last four reviews..." in the comment thread is a clear win.

The second thing AI reviewers are good at is mechanical pattern matching against well-known antipatterns. The same patterns that have been on the OWASP Top 10 for fifteen years. The same patterns that have been in every senior interview question for ten years. The same patterns that show up in a thousand training-set blog posts.

If you write a SQL query by concatenating a string with req.query.user, an AI reviewer is going to spot it. If you skip CSRF protection on a state-changing endpoint, it'll spot it. If you log a raw password, it'll spot it. If you commit a JWT secret, it'll spot it.

What both of these categories have in common is that the code reveals the problem. The function looks suspicious. The diff is the evidence. The reviewer doesn't need to know what your system does - it only needs to read the lines you handed it.

This is the half of code review that AI is genuinely changing. And if your team treats AI review as exactly this much and no more, you'll get a real productivity win with very little risk.

The problem starts the moment you start expecting it to do the other half.

The Other Half: Correctness, Intent, And Where Bugs Actually Live

Real bugs almost never live in the code you can see in the diff. They live in the relationship between the code in the diff and the rest of the system.

Think about the last few real bugs your team shipped. Walk through them. How many of them were caught by:

  • A reviewer noticing that the new endpoint duplicated logic from another endpoint, and now both versions disagreed?
  • A reviewer remembering that the field account.status could be pending_review only in tenants migrated before 2022, and the new code didn't handle that case?
  • A reviewer realizing that the new background job ran every five minutes, but the table it queried got partitioned by date last quarter, and the query was about to start scanning the entire archive partition?
  • A reviewer noticing that the new logic was correct in isolation, but the caller already did the same check three frames up, and now the count was off by one?

None of those bugs are visible in the diff. The diff looks fine. The diff is fine, locally. The bug lives in the conversation between the diff and everything outside it - the other twenty thousand lines of your codebase, the migration that ran two years ago, the operational reality of how the system runs in production.

This is where AI code review hits its hardest ceiling, and it's worth being precise about why. It's not that the model is bad. It's that the information needed to catch the bug isn't in the prompt. The reviewer is reading the diff. It might be reading the surrounding file. It might even be reading some retrieved chunks of your codebase. But it isn't reading:

  • The Slack thread from two years ago where the team decided that all auth checks happen at the middleware layer, not the controller.
  • The runbook that says this service runs in three regions and the new code's assumption of a single timezone breaks two of them.
  • The product manager's verbal decision that "soft delete" means hidden-from-list-but-still-billable, not gone.
  • The unwritten rule that any for await in this codebase needs a concurrency limit because the database connection pool is sized for ten.

A senior reviewer who's worked on your team for two years catches these because the system lives in their head. The AI catches them only if some surface artifact of those decisions made it into the code or into the context window. Most of the time, none of it did.

The failure mode here isn't wrong feedback. It's confident absent feedback. The AI reviewer doesn't flag the bug because it doesn't see the bug. And worse, it tells you "no issues found", which sounds like an affirmative review, not an admission of partial coverage. A human who didn't know the codebase well would at least hesitate. A model doesn't hesitate. That's the false confidence.

The fix isn't to expect the model to do more. It's to stop treating its silence as evidence.

Security Review Is The Sharpest Edge Of This Problem

Security is where the gap between "what looks suspicious in the diff" and "what's actually exploitable" gets the widest, the fastest.

Consider three diffs:

diff-1.py

@app.route("/users/<user_id>")
def get_user(user_id):
    query = f"SELECT * FROM users WHERE id = {user_id}"
    return db.execute(query).fetchone()

Enter fullscreen mode Exit fullscreen mode

This is a SQL injection. Every AI reviewer alive will catch it. It's in the training data of every model from every era. It's also unlikely to ship in any team that has any review at all.

diff-2.py

@app.route("/users/<user_id>")
@authenticated
def get_user(user_id):
    user = db.users.find_one({"id": user_id})
    return user.to_dict()

Enter fullscreen mode Exit fullscreen mode

This looks clean. There's an @authenticated decorator. The query is parameterized. The return is structured. An AI reviewer reads this and says "looks good" - and on the surface, it does.

But this might be an Insecure Direct Object Reference (IDOR) vulnerability. There's no check that the authenticated user is allowed to fetch this particular user_id. Anyone who's logged in can read anyone else's profile.

The model can't catch this without knowing the intent of your authorization model. Does your system let authenticated users read all other users? Maybe - it's a social app. Or maybe not - it's a healthcare app and each user can only read themselves and their dependents. The diff doesn't say which. The reviewer doesn't know which. So it defaults to a comfortable answer, which is silence.

diff-3.py

@app.route("/teams/<team_id>/invite", methods=["POST"])
@authenticated
def invite_member(team_id):
    email = request.json["email"]
    team = db.teams.find_one({"id": team_id})
    team.invite(email)
    return {"ok": True}

Enter fullscreen mode Exit fullscreen mode

Same shape, harder to spot. Even if the model checks for the user's authorization to act on team_id, it might miss that request.json["email"] is not validated, that the same endpoint can be used to enumerate which emails are already members based on the response shape, that the rate limit on this endpoint is missing because the team's existing pattern is to put rate limits on the gateway and this new endpoint is registered through a different path. None of that is visible in the eight lines you can see.

This pattern repeats across every security category. Authorization bugs depend on the rules of your domain. Race conditions depend on the concurrency model your runtime actually uses in production. Cryptographic mistakes depend on which threat model you've accepted. Secrets handling depends on which systems the data flows through after this code returns. None of it is in the diff. All of it is in your team's head.

The AI reviewer is genuinely useful as a first pass on security - it'll catch the patterns that match the training data, the OWASP-shaped problems, the obvious dumb stuff. The danger is treating that first pass as a security review. It isn't. Real security review needs someone who knows what your application is for, what data it holds, who's allowed to do what, and what an attacker would actually want.

Warning
When the AI reviewer says "no security issues found", read it as "no patterns from my training set matched the diff". That is not the same sentence.

The Hallucination Problem In Review Specifically

Hallucination in code generation is a known and well-discussed failure mode. Models invent function names, package versions, config flags, API endpoints. You've probably watched a model confidently import a module that doesn't exist.

What's less discussed is what hallucination looks like in code review. The shape is different - and arguably more dangerous - because the model isn't writing code you'll run. It's making assertions you'll act on.

A reviewing model can hallucinate in three distinct ways, and each one bites a different way.

Phantom references. The reviewer comments: "This is similar to the pattern in src/auth/middleware.py where we already handle this case." You open src/auth/middleware.py. There is no such pattern. There might not even be a file at that path. The model invented a plausible reference because that's what its training distribution rewards.

You can spot this one if you check, but the dangerous version is when the reference is almost real - the file exists, the function name is close but slightly wrong, the pattern is similar but not identical. You scan it, decide "yeah, that looks consistent", and merge. The reviewer has just convinced you of a fact that isn't quite true.

Phantom guarantees. The reviewer comments: "The framework handles input validation for you here, so you don't need to add it explicitly." Sometimes this is true. Sometimes the framework has some validation but not the kind that matters for this endpoint. Sometimes the framework had this feature in v3 and you're on v5 and they removed it. Sometimes the framework never had it and the model is mixing it up with a different framework's docs.

You're now relying on an assertion about a system you didn't verify. The diff didn't change. The vulnerability is now live, and the reasoning that justified shipping it is a sentence that sounded confident in a review thread.

Phantom approvals. The reviewer reads the diff, doesn't understand a chunk of it, and chooses safety: it says nothing about that chunk, and says positive things about the parts it does understand. The overall summary lands as "looks good". You read the summary. You don't notice that the most complex part of the diff was never actually addressed.

This is the quietest failure mode and the easiest to miss. The reviewer didn't say anything wrong. It just didn't say anything about the part that mattered. And because there's no visual indicator of "I read this and have no comment" vs "I didn't really understand this and have no comment", you can't tell the difference.

The defence against all three is the same and it's old-fashioned: don't trust assertions. When the AI reviewer references a file, open the file. When it claims the framework does X, find the docs. When the diff has a tricky section and the AI didn't comment on it, that's a signal, not a relief.

This is the discipline that turns AI review from a confidence machine into a useful one. The model is allowed to say things you'd never have noticed. It's not allowed to be the last layer of trust on anything that matters.

Venn diagram comparison: AI Reviewer catches style consistency, naming drift, obvious nullability, dead code, and classic OWASP patterns; Human Reviewer covers authorization rules, business invariants, cross-service contracts, and operational reality. The thin overlap holds local correctness and surface-level smells.

Designing A Review Workflow That Actually Works

Once you accept that AI review is great at one half of the job and structurally incapable of the other half, the workflow design becomes obvious. You arrange the two halves in series, not in parallel, and you give each one the job it can actually do.

Here's the shape of a workflow that gets the upside.

Step 1 - AI reviewer runs first, as a lint pass. The moment a pull request opens, the AI reviewer sweeps it. It flags style issues, naming inconsistencies, obvious antipatterns, classic security patterns, missing error handling, contradictory documentation. It posts these as inline comments on the diff, the same way a linter would.

The author addresses these before any human reviewer is paged. This is the whole productivity win - the senior engineer never has to write "please use the existing util for this" again. The boring layer is done. The author shows up to human review with a diff that's already past the obvious objections.

Step 2 - Author writes the description that the AI didn't. This is the step that gets cut and shouldn't. The AI is reviewing the code. The human reviewer needs to review the change. A change is the code plus the intent plus the constraints plus the trade-offs the author made.

The author writes - in plain English - what this change does, why now, what alternatives they considered, what the rollout plan is, what they're explicitly not trying to solve. If you've never read Tigran Sloyan's or Will Larson's writing on this, the short version is: a PR description is for the next person who reads the commit in three years, not for you today.

A good description here is also the thing that catches the author's own hallucinations. If you can't explain in two paragraphs why this change is correct, you've found the actual problem.

Step 3 - Human reviewer focuses on what the AI can't see. With the lint layer handled and the description written, the human reviewer's attention can land on the real questions:

  • Does this change match what we agreed to build?
  • Does it interact correctly with the rest of the system?
  • Are the security invariants of this product preserved, given who the users are and what data they hold?
  • Is this the right unit of change to ship, or should it be split, sequenced, or guarded behind a feature flag?
  • What are we not going to be able to undo after this merges?

These are the questions that need a person who knows the codebase and the product. They're the questions you wanted the AI to handle and it can't.

Step 4 - Critical paths get an explicit "AI didn't review this" gate. Any change to authentication, authorization, payments, data deletion, migrations, or anything else where the worst-case outcome is "the company gets fined or sued" carries a flag in your review template: "This change touches a critical path. AI review is not sufficient. Require N human approvals with one being from ."

This isn't because the AI's review is wrong on critical paths. It might be perfectly fine. It's because the cost of being wrong is asymmetric, and you don't let asymmetric risks ride on confidence-shaped reassurance.

Step 5 - Treat AI review output as evidence, not verdict. When the AI says "no issues found", that is not a green light. It's an absence of red flags from a system that can only see a fraction of them. Your team's mental model of an AI review needs to be: "the obvious problems are probably caught; the subtle ones are not addressed either way". The decision to merge still belongs to a human and a passing test suite.

This shape works. It doesn't deliver the "agents review your PRs and you ship faster forever" narrative - but it delivers something better, which is fewer comments your senior engineers hate writing and more attention on the parts of review that actually prevent incidents.

Five-stage horizontal review pipeline: PR opened, AI lint pass, author writes description (catches author hallucinations), human review (focuses on what AI can't see), merge. A separate red branch requires two human approvals for critical paths.

What This Means For The Senior Engineer

If you're a senior engineer reading this, the practical shift is small and worth doing deliberately.

You're not going to stop using AI reviewers - they're too useful at the lint layer to give up. But you're going to stop deferring to them on anything that matters. When the AI says "looks good", you're going to read it as "the cheap problems aren't here, what about the expensive ones". When the AI references something in the codebase, you're going to confirm it. When the AI gives you a confident-sounding explanation, you're going to ask the question "how would I know this was wrong?" before you accept it.

You're also going to write better PR descriptions, because once the AI handles the lint layer, the bottleneck in review moves to the human reviewer's ability to understand the change. That's a writing problem, not a coding problem, and it's the one part of code review that has gotten more important since AI showed up, not less.

And you're going to push back when leadership says "we have AI review now, we can have fewer humans on it". The answer is no, and the reason isn't sentiment - it's that the half of the job AI doesn't do is the half where the bugs that cost real money live. You'd rather have one AI reviewer plus a careful senior than two AI reviewers and a fast merge button.

The question in the title of this piece - assistant or false confidence machine - isn't really about the tool. It's about the team. The same model, in the same codebase, on the same diff, is one or the other depending on whether a human is treating its output as evidence or as a verdict.

If you remember anything from this, remember that distinction. AI review is evidence. Humans make the verdict. The day you flip those two roles is the day your incident channel gets a lot louder.


Originally published at nazarboyko.com.