AI-Powered Code Review with LLMs 2026: Automate Bug Detection and Security Audits
Advertisement
AI Code Review 2026: Your Always-On Senior Engineer
The best code review is the one that happens instantly, every time. AI code reviewers catch bugs, security issues, and style problems before human reviewers ever see the PR.
- Why AI Code Review Works
- Core Review Engine
- Security Vulnerability Scanner
- GitHub Actions Integration
- Multi-Language Support
- Custom Review Rules
- Performance Analysis
- Pre-commit Hook
- Cost Optimization
Why AI Code Review Works
Traditional linters catch syntax errors. AI reviewers understand intent, context, and logic:
- SQL injection vulnerabilities in dynamic queries
- Race conditions in async code
- Memory leaks in resource handling
- Business logic bugs ("this returns wrong results for empty arrays")
- Performance issues ("this is O(n²) — here's the O(n) version")
Core Review Engine
from openai import OpenAI
import ast
import re
client = OpenAI()
SYSTEM_PROMPT = """You are a senior software engineer performing code review.
Analyze the provided code diff and return a JSON array of review comments.
Each comment must have:
- line: line number (or null for general comments)
- severity: "critical" | "warning" | "suggestion" | "praise"
- category: "bug" | "security" | "performance" | "readability" | "logic"
- message: clear explanation of the issue
- suggestion: specific fix or improvement
Focus on:
1. CRITICAL: bugs, security vulnerabilities, data loss risks
2. WARNING: performance issues, error handling gaps, logic errors
3. SUGGESTION: improvements, better patterns, test coverage
4. PRAISE: well-written code worth acknowledging
Return ONLY valid JSON. No markdown, no explanation."""
def review_code(diff: str, filename: str, context: str = "") -> list[dict]:
"""Review a code diff and return structured feedback."""
prompt = f"""File: {filename}
Context: {context or 'General code review'}
Code diff:
{diff}
Return JSON array of review comments."""
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": prompt},
],
response_format={"type": "json_object"},
temperature=0.2,
)
import json
result = json.loads(response.choices[0].message.content)
return result.get("comments", result) if isinstance(result, dict) else result
Security Vulnerability Scanner
SECURITY_PROMPT = """You are a security engineer specializing in code security audits.
Analyze the code for security vulnerabilities. Return JSON with:
- vulnerabilities: array of {type, severity, line, description, cwe_id, fix}
- risk_score: 0-10
- summary: brief security assessment
Check for: SQL injection, XSS, CSRF, path traversal, command injection,
hardcoded secrets, insecure deserialization, broken auth, sensitive data exposure."""
def security_scan(code: str, language: str = "python") -> dict:
"""Scan code for security vulnerabilities."""
import json
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": SECURITY_PROMPT},
{"role": "user", "content": f"Language: {language}\n\nCode:\n```{language}\n{code}\n```"},
],
response_format={"type": "json_object"},
temperature=0,
)
return json.loads(response.choices[0].message.content)
# Example vulnerable code
vulnerable_code = """
def get_user(user_id):
query = f"SELECT * FROM users WHERE id = {user_id}" # SQL injection!
return db.execute(query)
def render_profile(name):
return f"<h1>Welcome {name}</h1>" # XSS!
API_KEY = "sk-abc123secretkey" # Hardcoded secret!
"""
result = security_scan(vulnerable_code)
print(f"Risk score: {result['risk_score']}/10")
for vuln in result['vulnerabilities']:
print(f"[{vuln['severity']}] {vuln['type']}: {vuln['description']}")
GitHub Actions Integration
# .github/workflows/ai-code-review.yml
name: AI Code Review
on:
pull_request:
types: [opened, synchronize]
jobs:
review:
runs-on: ubuntu-latest
permissions:
pull-requests: write
contents: read
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install dependencies
run: pip install openai PyGithub
- name: Run AI Code Review
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
REPO: ${{ github.repository }}
run: python .github/scripts/ai_review.py
# .github/scripts/ai_review.py
import os
import subprocess
import json
from openai import OpenAI
from github import Github
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
gh = Github(os.environ["GITHUB_TOKEN"])
def get_pr_diff():
result = subprocess.run(
["git", "diff", "origin/main...HEAD", "--unified=5"],
capture_output=True, text=True
)
return result.stdout
def post_review_comments(repo_name, pr_number, comments):
repo = gh.get_repo(repo_name)
pr = repo.get_pull(int(pr_number))
# Post summary comment
critical = [c for c in comments if c.get("severity") == "critical"]
warnings = [c for c in comments if c.get("severity") == "warning"]
summary = f"""## 🤖 AI Code Review
**{len(critical)} critical issues** | **{len(warnings)} warnings** | **{len(comments)} total comments**
"""
for comment in comments:
icon = {"critical": "🔴", "warning": "🟡", "suggestion": "💡", "praise": "✅"}.get(comment["severity"], "📝")
summary += f"{icon} **[{comment['category']}]** {comment['message']}\n"
if comment.get("suggestion"):
summary += f" > 💡 {comment['suggestion']}\n\n"
pr.create_issue_comment(summary)
print(f"Posted review with {len(comments)} comments")
diff = get_pr_diff()
if len(diff) > 100:
comments = review_code(diff[:8000], "PR diff")
post_review_comments(
os.environ["REPO"],
os.environ["PR_NUMBER"],
comments
)
Multi-Language Support
LANGUAGE_CONTEXTS = {
"python": "Focus on: type hints, exception handling, resource management (context managers), list comprehensions vs loops",
"javascript": "Focus on: async/await patterns, null checks, prototype pollution, XSS in DOM manipulation",
"typescript": "Focus on: strict null checks, type assertions, generic constraints, discriminated unions",
"go": "Focus on: error handling patterns, goroutine leaks, interface satisfaction, defer usage",
"rust": "Focus on: ownership, borrowing, lifetime annotations, unwrap() usage",
"sql": "Focus on: query performance, indexes, N+1 patterns, injection vulnerabilities",
}
def review_with_language_context(code: str, language: str) -> list[dict]:
context = LANGUAGE_CONTEXTS.get(language.lower(), "General best practices")
return review_code(code, f"code.{language}", context)
Custom Review Rules
CUSTOM_RULES = """
Additional rules for this codebase:
1. All database queries must use parameterized queries — never string formatting
2. All user inputs must be validated with Pydantic models
3. Async functions must have timeout handling
4. All new endpoints must include rate limiting
5. Secrets must come from environment variables, never hardcoded
6. All public functions must have docstrings
"""
def review_with_custom_rules(diff: str) -> list[dict]:
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": SYSTEM_PROMPT + "\n\n" + CUSTOM_RULES},
{"role": "user", "content": f"Review this diff:\n{diff}"},
],
response_format={"type": "json_object"},
temperature=0.1,
)
import json
result = json.loads(response.choices[0].message.content)
return result.get("comments", [])
Performance Analysis
PERF_PROMPT = """Analyze this code for performance issues. Return JSON:
{
"issues": [{"description", "impact": "high/med/low", "line", "optimization"}],
"complexity": {"time": "O(?)", "space": "O(?)"},
"score": 1-10,
"quick_wins": ["specific optimizations with expected speedup"]
}"""
def analyze_performance(code: str, language: str = "python") -> dict:
import json
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": PERF_PROMPT},
{"role": "user", "content": f"```{language}\n{code}\n```"},
],
response_format={"type": "json_object"},
temperature=0,
)
return json.loads(response.choices[0].message.content)
Pre-commit Hook
#!/usr/bin/env python3
# .git/hooks/pre-commit (chmod +x)
import subprocess
import sys
import os
from openai import OpenAI
def main():
# Get staged changes
result = subprocess.run(
["git", "diff", "--cached", "--unified=3"],
capture_output=True, text=True
)
diff = result.stdout
if len(diff) < 50:
sys.exit(0) # Nothing to review
print("🤖 Running AI code review...")
client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))
response = client.chat.completions.create(
model="gpt-4o-mini", # Fast + cheap for pre-commit
messages=[{
"role": "user",
"content": f"""Quick review this diff. Only flag CRITICAL issues (bugs, security).
Be concise. Format: ISSUE: [description] on line [N]
{diff[:3000]}"""
}],
max_tokens=500,
temperature=0,
)
review = response.choices[0].message.content
if "ISSUE:" in review:
print("\n⚠️ AI Review found issues:\n")
print(review)
answer = input("\nCommit anyway? [y/N]: ")
if answer.lower() != "y":
sys.exit(1)
print("✅ AI review passed")
if __name__ == "__main__":
main()
Cost Optimization
| Approach | Model | Cost/1K lines | Speed |
|---|---|---|---|
| Full review | gpt-4o | ~$0.15 | 3-5s |
| Pre-commit check | gpt-4o-mini | ~$0.01 | 1-2s |
| Security scan only | gpt-4o | ~$0.10 | 2-3s |
| Batch nightly | gpt-4o | ~$0.05 | async |
AI code review pays for itself by catching one production bug per month. At $0.15 per PR, it's cheaper than 30 seconds of a senior engineer's time.
Advertisement