Claude Code as a Security Scanner: Beyond Pattern Matching

Tools like ESLint, Semgrep, and Bandit catch what they are programmed to find: known patterns, common injection strings, deprecated API calls. They are fast, reliable, and deterministic. They are also blind to anything that requires understanding what your code is supposed to do.

Claude Code operates differently. It reads code the way a human security researcher would — tracing data flows across files, understanding business logic, and reasoning about what could go wrong given the specific context of your application. This makes it effective at a class of vulnerabilities that pattern-matching tools routinely miss.


What Traditional Scanners Cannot Find

flowchart TD
    subgraph Traditional[Traditional Static Analysis]
        P1[Known injection patterns]
        P2[Deprecated API calls]
        P3[Common misconfigurations]
        P4[Syntax-level issues]
    end
    subgraph Claude[Claude Code Analysis]
        C1[Business logic flaws]
        C2[IDOR vulnerabilities]
        C3[Multi-step workflow exploits]
        C4[Cross-file data flow issues]
        C5[Auth state inconsistencies]
    end
    Traditional -->|misses| Claude

Business logic flaws are the hardest category to catch with automation. Consider a scenario where a discount code is validated at checkout but stored in the session — and the session persists across authentication state changes. A scanner looking for SQL injection will not find this. Claude, reading the checkout flow end-to-end, can trace the discount code from validation through storage through redemption and flag that the code survives logout.

IDOR vulnerabilities (Insecure Direct Object References) require understanding the relationship between your URL parameters and your data model. A route that accepts /api/orders/:id without checking that the authenticated user owns that order is exploitable — but only if the scanner understands what “owns” means in your domain.

Multi-step workflow exploits — broken password resets, email verification bypasses, payment state mismatches — require following a complete user journey across multiple endpoints, often across multiple files.


How to Run a Security Audit

Option 1: Direct prompt

For a specific file or component:

Audit src/api/checkout.ts for security vulnerabilities.

Trace data flows end to end — follow the cart data from the request through
validation, pricing, discount application, and payment processing.

Look specifically for:
- Auth and authorization gaps (can an unauthenticated user reach any step?)
- State that persists across user sessions incorrectly
- Places where user-supplied values touch database queries or file paths
- Business logic that could be exploited (price manipulation, discount reuse)

For each finding: severity (critical/high/medium/low), exact location,
and why it is exploitable in this specific codebase.

Option 2: Custom slash command

Create .claude/commands/security-audit.md in your project:

Review $ARGUMENTS for security vulnerabilities.

Trace data flows end-to-end across related files — not just the file provided.

Check for:
- Injection risks: SQL, command injection, path traversal
- Authentication and authorisation gaps
- Sensitive data exposure in logs or responses
- Business logic flaws specific to this application's domain
- Insecure Direct Object References
- Multi-step workflow vulnerabilities

Rate each finding: critical / high / medium / low
Include: file path, line number, description, and why it is exploitable.
Do not make any code changes — report only.

Then run it:

/project:security-audit src/api/payments/

The Audit Workflow

sequenceDiagram
    participant Dev as Developer
    participant Claude as Claude Code
    participant Files as Codebase

    Dev->>Claude: security-audit src/api/checkout.ts
    Claude->>Files: Read checkout.ts
    Claude->>Files: Trace imports - read auth middleware
    Claude->>Files: Trace imports - read cart service
    Claude->>Files: Read payment processor integration
    Claude-->>Dev: 3 findings: 1 high, 2 medium
    Dev->>Dev: Review each finding
    Dev->>Claude: Fix the high severity finding in checkout.ts
    Claude->>Files: Edit checkout.ts
    Claude-->>Dev: Fix applied - here is what changed and why
    Dev->>Dev: Review diff, approve change

The human-in-the-loop is deliberate. Claude reports findings and explains them but does not automatically patch them. Security decisions should stay human-controlled — an automated fix to a security issue can introduce a different vulnerability if the surrounding context is not fully understood.


What Claude Catches vs What It Misses

CategoryClaudeSemgrep / ESLint
SQL injection (parameterised)GoodGood
Business logic flawsExcellentPoor
IDORGoodPoor
Multi-step exploitsGoodVery poor
Known CVE patternsLimitedExcellent
Supply chain issuesPoorGood (with plugins)
PerformanceNoNo

The right approach is both. Run your standard linters in CI for fast, deterministic coverage of known patterns. Use Claude Code for deeper audits before major releases, after significant changes to auth or payment flows, or when onboarding to an unfamiliar codebase.


Practical Tips

Be specific about what to audit. “Audit the whole repo” produces shallow results across everything. “Audit the checkout flow” produces deep results where it matters.

Provide business context. The more Claude understands about what your application is supposed to do, the better it can identify where it does something unintended. Include a brief description of the feature you are auditing.

Iterate on findings. Ask Claude to explain its reasoning. “Why is this IDOR exploitable specifically?” often reveals whether it is a real finding or a false positive, faster than manually tracing the code yourself.

Run audits on a clean context. Start a fresh session for security audits. Stale context from unrelated work can reduce the quality of analysis.


Integration with CI

For teams wanting automated security feedback on pull requests, Claude can run as part of a GitHub Actions workflow:

name: Security Review
on: [pull_request]

jobs:
  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Claude Security Audit
        run: |
          changed=$(git diff --name-only origin/main...HEAD | grep -E '\.(ts|js|py|go)$')
          if [ -n "$changed" ]; then
            echo "$changed" | xargs -I{} claude -p \
              "Security audit of {}: check for auth gaps, injection risks, and business logic flaws. Report findings with severity." \
              --output-format json
          fi          
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}

This runs a targeted audit on only the files changed in the PR — keeping it fast and focused.

Abhay

Abhay Pratap Singh

DevOps Engineer passionate about automation, cloud infrastructure, and self-hosted tools. I write about Kubernetes, Terraform, DNS, and everything in between.