← All guides AI Release
RU Subscribe to @ai_release1

How to Scan AI-Generated Code for Vulnerabilities

Updated: 21.10.2026 · AI Release · @ai_release1
How to Scan AI-Generated Code for Vulnerabilities

TL;DR

Requirements and setup

Illustration: Requirements and setup
Illustration: Requirements and setup

What to do: install three independent scanner layers and confirm each one runs on your machine before you point it at the AI-written code.

Why: AI assistants generate a lot of code fast, and the typical failure modes are different from human-written code: a live API key pasted into a config file, a dependency name the model invented, and a plausible-looking function with an injection bug. No single tool covers all three, so you stack them.

LayerQuestion it answersToolWhat it reads
SecretsDid the assistant paste a real key or token into a file?Gitleaksthe whole repo, including Git history
SCA (software composition analysis — checks third-party libraries for known CVEs)Does a library version I depend on have a published vulnerability?`pip-audit` (Python), `npm audit` (Node.js)lockfiles and manifests
SAST (static application security testing — reads source code without running it)Does the code contain injection, weak randomness, unsafe deserialization, etc.?Semgrepsource files
Container / IaCDoes a Dockerfile or YAML manifest run as root or expose a port?Trivy`Dockerfile`, `*.yaml`

Install the scanners:

pipx install pip-audit
brew install gitleaks semgrep trivy

On Windows use winget or scoop instead of brew — check each tool's documentation for the current package name.

Example: after installation, gitleaks version prints a single version string and semgrep --version prints a version plus a Python path. If a command prints command not found, the binary is not on your PATH — reopen the terminal or add ~/.local/bin to PATH.

Before the first run, exclude directories that produce noise and false positives:

cat > .semgrepignore <<'EOF'
node_modules/
.venv/
dist/
build/
.cursor/
EOF

Why this works: Semgrep and Gitleaks both walk the filesystem; excluding vendored and tool-cache directories stops them from reporting the same issue hundreds of times.

Step 1. Freeze the AI-generated diff and verify every dependency name

Illustration: Step 1. Freeze the AI-generated diff and verify every dependency name
Illustration: Step 1. Freeze the AI-generated diff and verify every dependency name

What to do: commit everything the assistant wrote onto a dedicated branch, then list every dependency the project declares and check that each package actually exists in its public registry.

Why: scanners only see committed files — a half-saved file in an editor is invisible to them. And a model occasionally references a package that does not exist; an attacker can register that name later and your next npm install pulls their code. That class of risk is invisible to CVE scanners because there is no CVE yet.

git switch -c sec/ai-code-review
git add -A
git commit -m "chore: freeze AI-generated code before security review"
git status --short
git diff --stat main...HEAD

Example output (your numbers will differ):

42 files changed, 3120 insertions(+), 118 deletions(-)

git status --short must print nothing — a clean tree means the scan covers exactly what is committed. If your agents create many small commits and you need a cleaner history for review, see Jujutsu or Git: What to Choose for AI Agent Workflows.

Now inventory the dependencies:

pip freeze > requirements.lock.txt
npm ls --depth=0

Check each direct dependency name against its registry:

npm view <package-name> version
pip index versions <package-name>

Example: if the assistant wrote import { parse } from "safe-json-parser-pro", run npm view safe-json-parser-pro version. A real package prints a version number. A hallucinated one prints:

npm error code E404
npm error 404 Not Found - GET https://registry.npmjs.org/safe-json-parser-pro - Not found

How to check: the commit exists (git log --oneline -1) and every package name in requirements.lock.txt and in package.json returns a version from the registry, not a 404.

Step 2. Run the three scanner layers into report files

Illustration: Step 2. Run the three scanner layers into report files
Illustration: Step 2. Run the three scanner layers into report files

What to do: run secrets, dependency, and static analysis in that order, and write each result to a machine-readable file inside reports/.

Why: order matters. A leaked key must be rotated within minutes, while a style-level SAST finding can wait. Writing reports to files gives you a diffable artifact you can attach to a pull request and compare between runs.

mkdir -p reports
gitleaks detect --source . --report-format json --report-path reports/gitleaks.json -v
pip-audit -r requirements.txt -f json -o reports/pip-audit.json
npm audit --audit-level=high
semgrep --config auto --sarif --output reports/semgrep.sarif .
trivy fs .

Why this works: Gitleaks matches entropy and known key patterns in text, pip-audit and npm audit compare your resolved versions against public CVE feeds, and Semgrep parses the code into a syntax tree so a finding like "user input reaches a SQL string" survives reformatting and renaming. SARIF is a JSON report format that code-scanning dashboards can read directly.

Example: a Semgrep finding looks like this on screen — python.lang.security.audit.formatted-sql-query, the file path, the line number, and a code snippet. A Gitleaks hit prints RuleID, File, Line, and a redacted Secret.

Wire the same commands into CI so no one has to remember them:

name: ai-code-security
on: [pull_request]
jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: pipx install pip-audit
      - run: pip-audit -r requirements.txt
      - run: npm audit --audit-level=high
      - run: gitleaks detect --source . --redact -v
      - run: semgrep --config auto --error .

If your team already runs Claude Code with subagents, put these commands in a subagent checklist so the reviewer agent always executes the same three layers — see Claude Code for Teams: Setting Up Subagents and a Shared AI Superagent.

How to check: ls -la reports/ lists gitleaks.json and semgrep.sarif, and every command above finished without a stack trace.

Step 3. Triage the reports and gate the merge

What to do: read the reports, fix the blocking findings, then re-run the scanners in "fail on finding" mode so the check can be used as a merge gate.

jq 'length' reports/gitleaks.json
jq -r '.[] | "\(.File):\(.StartLine) \(.RuleID)"' reports/gitleaks.json

Example: jq 'length' printing 0 means no secrets were found anywhere in history. Any other number is a list you must work through line by line.

Fix each item in this order: rotate the leaked credential first (deleting the file does not invalidate the key), then upgrade or replace the vulnerable dependency, then patch the SAST findings. After fixing, re-run with hard failure enabled:

gitleaks detect --source . --exit-code 1 --redact
semgrep --config auto --error .
echo $?

How to check: echo $? prints 0, the CI job named ai-code-security is green on the pull request, and git log -1 --stat shows the fix commit. If the number is not 0, a finding is still open — go back to the report.

Troubleshooting

Problem. The install step fails on a package the assistant recommended

Problem. Gitleaks blocks the build on a test fixture

cat > .gitleaks.toml <<'EOF'
[allowlist]
  paths = ['''tests/fixtures/.*''']
EOF
gitleaks detect --source . --config .gitleaks.toml --exit-code 1 --redact

Problem. The CI step fails even though the local run passed

Summary and next steps

You now have a repeatable gate: freeze the AI diff, verify dependency names, run secrets/SCA/SAST into reports/, and merge only when echo $? returns 0. Next, add the same job to every repository where assistants write code, and if your code cannot leave your network, route the review through a self-hosted model as described in How to connect a local LLM to Claude Code.

FAQ

Can Cursor or Claude Code introduce security vulnerabilities?

Yes — the assistant writes code faster than a human reviews it, and the recurring issues are leaked credentials, invented package names, and plausible-but-unsafe logic such as string-concatenated SQL. The scanners in this guide target exactly those three categories.

Does Cursor have a built-in security scanner?

This guide does not depend on any editor feature; it uses external scanners so the result is the same regardless of which assistant wrote the code. Check the vendor's documentation for the current built-in feature set.

Is it safe to send proprietary code to a cloud AI assistant?

That depends on your contract and data policy, which this guide cannot verify for you. If policy forbids sending code to a third party, keep the scanners local and use a self-hosted model for the review step.

How often should I run these scanners?

On every pull request via CI, plus one full-history Gitleaks run whenever a new contributor or repository is onboarded, because a secret committed months ago stays in history until it is rotated.

🤖 AI summary