DEV Community

Atlas Whoff
Atlas Whoff

Posted on

The AI Coding Velocity Gap: Why Faster Code Ships More Vulnerabilities

The AI Coding Velocity Gap: Why Faster Code Ships More Vulnerabilities

Research out this month found a direct correlation between AI coding tool adoption and a 4x increase in critical security findings in production code. This isn't an anti-AI take — it's a systems problem with a systems solution.

The Data

The pattern is consistent across organizations that adopted AI coding tools at scale in 2025-2026:

  • Velocity increased ~3x: code shipped per engineer per sprint tripled
  • Critical findings increased ~4x: high/critical security issues in production quadrupled
  • Remediation lag doubled: time from finding to fix grew because volume outpaced review capacity

The density problem is the real issue. It's not that AI writes more buggy code per line — it's that you ship so many more lines, the absolute count of vulnerabilities scales faster than your security review capacity.

Why It Happens

AI coding tools are optimized for correctness on the happy path. They're excellent at:

  • Making code that works as described
  • Following the pattern you showed them
  • Generating boilerplate quickly

They're systematically weak at:

  • Understanding authorization context across a large codebase
  • Inferring which data is sensitive without explicit labeling
  • Recognizing second-order injection risks in multi-step data flows
  • Applying security constraints that aren't in the immediate context window

The result: the code works exactly as specified, but the specification was missing the security constraint.

The 4 Scenarios That Create Most Issues

1. Context Window Authorization Blindness

# Agent sees this endpoint and generates a "similar" one:
@app.get("/api/user/{user_id}/profile")
async def get_profile(user_id: int, current_user = Depends(get_current_user)):
    return db.query(UserProfile).filter_by(id=user_id).first()

# Agent generates:
@app.get("/api/user/{user_id}/documents")
async def get_documents(user_id: int):  # ← missing auth
    return db.query(Document).filter_by(owner_id=user_id).all()
Enter fullscreen mode Exit fullscreen mode

The authorization dependency was in another file, out of context. The new endpoint matches the pattern syntactically but drops the security constraint.

2. Implicit Trust Escalation

AI tools generate integration code that trusts external API responses. When that external API is partially attacker-controlled (third-party webhooks, user-provided URLs, etc.), the generated code creates a trust escalation path.

3. Over-Permissioned Database Queries

AI-generated ORM queries often fetch full objects when filtered projections are safer. Not a vulnerability in isolation, but creates exposure surface if another vulnerability allows partial data exfiltration.

4. Secret Interpolation in Logs

AI tools write verbose debug logging. In codebases where secrets flow through request context (JWTs, API keys), generated logging code often captures more than intended.

The 4-Layer Mitigation Stack

This isn't about using AI tools less. It's about compensating for their systematic blind spots.

Layer 1: Security Context Files

Put your security constraints where the AI can see them. A SECURITY.md or security-context.md at the project root should define:

  • Which parameters are user-controlled and untrusted
  • Which tables/fields contain sensitive data
  • Required auth patterns for each resource type
  • Forbidden patterns (never log X, always validate Y)

AI coding tools read context files. If your security rules are in context, they apply them.

Layer 2: Static Analysis in CI, Not Just Code Review

Semgrep, Bandit, and similar tools catch the categories above reliably. The key is treating these as blocking checks in CI — not post-merge suggestions. The velocity you gain from AI tools is meaningless if you deploy vulns to production.

# .github/workflows/security.yml
- name: Semgrep
  uses: semgrep/semgrep-action@v1
  with:
    config: >
      p/default
      p/owasp-top-ten
      p/secrets
  env:
    SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}
Enter fullscreen mode Exit fullscreen mode

Layer 3: Auth Layer Tests

For every new endpoint or mutation, require a test that asserts the endpoint rejects unauthenticated requests AND requests from a user who doesn't own the resource. This takes 10 minutes per endpoint and catches the authorization blindness pattern mechanically.

def test_get_documents_requires_auth():
    resp = client.get("/api/user/1/documents")  # no auth header
    assert resp.status_code == 401

def test_get_documents_enforces_ownership():
    resp = client.get("/api/user/2/documents",  # user 1 accessing user 2
                      headers={"Authorization": user1_token})
    assert resp.status_code == 403
Enter fullscreen mode Exit fullscreen mode

Layer 4: AI-Assisted Security Review

Ironically, the same tools that create the vulnerability gap are good at finding it — if you prompt correctly.

Before shipping an AI-generated feature:

Review this code for security issues. Focus on:
1. Authorization: does every endpoint check the requesting user owns the resource?
2. Input validation: which parameters are user-controlled and untrusted?
3. Data exposure: is any sensitive field returned that isn't needed?
4. Logging: are any secrets, tokens, or PII captured in logs?
Enter fullscreen mode Exit fullscreen mode

Claude Mythos (the model Anthropic used to find thousands of zero-days in production systems this month) is exceptional at this. The same capability scales to your codebase.

The Takeaway

AI coding tools are net positive on security when you compensate for their blind spots. The teams getting hurt are the ones who adopted AI velocity without updating their security process to match.

Velocity without compensating controls isn't a developer problem — it's a process debt that scales with every sprint.


What's your current security layer for AI-generated code? I'm especially curious if anyone has a working solution for the authorization context problem.

Top comments (0)