Why Detecting AI Code Matters
As AI coding assistants become standard in development workflows, the question is no longer whether there is AI-generated code in your codebase β there almost certainly is. The relevant questions are: where is it, and does your review process account for its specific risk profile?
AI-generated code has a distinctive vulnerability profile. It is more likely to have certain classes of security issues (BOLA, mass assignment, hardcoded credentials) and less likely to have others (weak password hashing, obvious injection). Knowing which parts of the codebase were AI-generated allows security reviewers to focus their attention on the highest-risk areas.
Not a quality judgment: Identifying AI-generated code is not about flagging it as bad β it is about reviewing it appropriately. AI code can be excellent or poor, just like human code. The goal is informed review, not rejection.
Structural Signals
AI code tends to have structural patterns that emerge from how language models generate text β producing well-formed, complete, self-contained units that may not fit seamlessly into the surrounding architecture.
Unusually complete and symmetric structure
Human developers write code incrementally β they start with the happy path, add error handling when it breaks, and refactor gradually. AI code tends to arrive fully formed with error handling, logging, and documentation already in place. This can look suspiciously polished:
# AI-generated: every branch handled, every case documented def process_payment(amount: float, currency: str, user_id: int) -> dict: """ Process a payment for the given amount. Args: amount: The payment amount in the specified currency currency: The ISO 4217 currency code user_id: The ID of the user making the payment Returns: dict: A dictionary containing status, transaction_id, and timestamp Raises: ValueError: If amount is negative or currency is invalid PaymentError: If the payment processor returns an error """ if amount <= 0: raise ValueError(f"Amount must be positive, got {amount}") if currency not in VALID_CURRENCIES: raise ValueError(f"Invalid currency: {currency}") # ... 40 more lines of equally symmetric code
A human-written equivalent of the same function in the same codebase might have incomplete docstrings, inconsistent error message formatting, or a TODO comment on a case that was deferred.
Inconsistency with surrounding code
AI code generated in isolation β without context about the full codebase β will have different patterns to the surrounding code. Different variable naming conventions, different error handling patterns, different logging formats. These stylistic discontinuities are one of the clearest signals of AI generation.
Comment Patterns
Comments are one of the clearest fingerprints of AI-generated code. AI tends to comment heavily and in a particular style β explanatory rather than contextual.
AI comment characteristics
- Explains what, not why: Human comments explain why a decision was made (
# Using bcrypt over argon2 because the deployment target lacks libsodium). AI comments explain what the code does (# Hash the password using bcrypt) - Uniform density: AI comments are evenly distributed. Human comments cluster around complex or non-obvious sections
- Generic phrasing: AI comments use generic phrases that apply to any code of that type, not phrases specific to the business context
- Section headers: AI frequently uses comment-as-section-header patterns (
# ===== User Authentication =====) that humans rarely use in the same file style
# Human comment (explains why): # Rate limit to 5 attempts β legal required us to implement # NIST 800-63B lockout policy after the Q3 audit finding # AI comment (explains what): # Check if the user has exceeded the maximum login attempts # If so, lock the account to prevent brute force attacks
Security Red Flags as Detection Signals
Certain security patterns appear much more frequently in AI-generated code than in carefully written human code. Their presence is a signal that the code may have been AI-generated and warrants closer security review.
Placeholder secrets
Values like "your-secret-key", "change-me", or "SECRET_KEY_HERE" as string literals in code
No ownership checks
Endpoints that query by ID without verifying the requesting user owns that resource
Full object returns
API endpoints returning entire database models rather than projected response schemas
Missing rate limits
Auth and API endpoints with no rate limiting, throttling, or lockout logic
Outdated dependencies
Package versions from 2β3 years ago that have since had CVEs β AI picks popular-at-training-time versions
JWT without expiry
JWT creation without exp claim, or with weak secrets in string literals
Do not mistake absence of signals for absence of AI: Well-prompted AI assistants can generate code without these patterns. The absence of security red flags does not mean code was human-written β it may mean the developer reviewed and corrected the AI output.
Git History Signals
Git history often reveals AI-generated code through unusual commit patterns that reflect how developers interact with AI tools.
Commit pattern signals
- Large single commits: AI generates complete implementations in one shot β a 500-line file appearing in a single commit with a generic message like "add user authentication" is a strong signal
- Commit timing: AI-assisted development often shows unusually large code additions in short time periods (200+ lines in 15 minutes)
- Followed by correction commits: A large AI-generation commit followed immediately by small fix commits (
fix typo,fix import,add missing validation) is a classic pattern of AI output being corrected - Commit messages describing the prompt: Developers sometimes use the AI prompt as the commit message:
add REST API for user management with JWT auth
# Suspicious pattern: large addition, then micro-fixes a3f9c21 add user auth service with JWT (+487 lines, 14 min ago) b8d2e14 fix import ( +2 lines, 8 min ago) c1e5f33 fix typo in error message ( +1 line, 6 min ago) d4a9b12 add missing password validation (+12 lines, 3 min ago)
Style and Naming Patterns
AI language models have consistent stylistic preferences that can be fingerprinted. These are not universal β they vary by AI system and have changed over model generations β but they are recognisable patterns.
Naming conventions
AI tends to use descriptive, full-word variable names (userAuthenticationService, currentActiveSubscription) rather than the abbreviated forms common in working codebases (authSvc, activeSub). This makes AI code very readable but creates stylistic discontinuity with surrounding code.
Error message style
AI error messages tend to be grammatically complete, formal sentences: "The provided email address is not in a valid format." Human error messages are typically more terse: "Invalid email format" or just "invalid email".
Import organisation
AI typically generates perfectly organised imports β grouped by standard library, third-party, local, alphabetically sorted within groups. Human-written files accumulate imports organically, often unsorted and ungrouped.
Automated Detection Tools
Several tools attempt automated detection of AI-generated code, though none are reliably accurate enough to be used as a definitive signal β they are one input among many.
Current approaches
- Statistical analysis: Tools like GPTZero (originally for text) have code variants β they look for the statistical regularity of AI outputs (low perplexity, high uniformity)
- Watermarking: Some AI coding tools embed statistical watermarks in their output β invisible to readers but detectable algorithmically
- Attribution via training data matching: Research tools can identify code that appears verbatim in training data β a signal that it was likely AI-generated from a memorised example
- IDE telemetry: Enterprise AI coding tools (Copilot for Business, Cursor Teams) provide audit logs of which code was accepted from AI suggestions β the most reliable detection method available
The most reliable signal: Ask the developer. Most engineers are transparent about which parts of their code were AI-generated, especially if your team has a culture of treating it as a normal and acceptable tool rather than something to hide.
Adapting Your Review Process
Once you can identify likely AI-generated code, the question is how to review it differently. The goal is not more review time β it is more targeted review time, focused on the areas where AI code is weakest.
AI code review checklist
- Run automated security scanning immediately β before human review. SAST and SCA will catch the most common AI vulnerability classes faster than a human can
- Check every endpoint for ownership validation β for each resource-returning endpoint, verify there is an explicit ownership or permission check
- Audit all credentials and secrets β search for placeholder strings, review all environment variable usage
- Review dependency versions β run SCA on any new dependencies AI introduced
- Test business logic manually β AI code passes happy-path tests but often fails ownership, rate limit, and boundary tests. Write these explicitly
- Verify stylistic consistency β confirm the AI code follows established patterns for error handling, logging, and data access in this codebase
Security-focused review over style review: It is less important whether AI code matches your naming conventions than whether it is secure. Prioritise the security checklist over stylistic feedback in review β style can be fixed in a follow-up; vulnerabilities cannot always be caught post-deployment.
Automate Security Review of AI Code
AquilaX automatically scans for the vulnerability classes AI-generated code consistently misses β so your reviewers can focus on what automated tools cannot catch.
Start Free Scan