If you use AI coding assistants (Cursor, Copilot, Windsurf), you already know the pattern: the code looks right, the tests pass, and then production breaks with a bug that was sitting in plain sight.
I built AINAScan to catch exactly those bugs — and today it scans entire projects via ZIP upload, not just single files.
🔗 ainascan.dev — try it free →
What it scans
48 patterns across 3 categories — pure AST analysis, no LLM guessing:
🛡 Security (24 patterns — BLOCK)
The ones that will get you in the news:
| Pattern | What it catches |
|---|---|
SQL_INJECTION_RISK |
f-string / %-format SQL — classic |
COMMAND_INJECTION |
subprocess + shell=True + user input |
PATH_TRAVERSAL |
open() with unvalidated user path |
XSS_RISK |
Unsanitized user input in response / Markup() without escaping |
INSECURE_DESERIALIZATION |
pickle.loads() / yaml.load() without SafeLoader — RCE |
DEBUG_MODE_RISK |
debug=True in Flask/FastAPI — exposes full stack traces in prod |
HARDCODED_SECRET |
api_key = "sk-abc123" literally in source |
SSRF_RISK |
HTTP request with user-controlled URL |
EVAL_EXEC_RISK |
eval()/exec() with dynamic input |
TYPE_UNSAFE_ACCESS |
float(d.get("k")) without None check — guaranteed TypeError
|
DB_SCHEMA_DRIFT |
SQL column not in actual DB schema — runtime crash |
| + 13 more | CORS, CSRF, IDOR, template injection, weak crypto... |
🤖 Vibe-Coding Structural Bugs (13 patterns — BLOCK)
These are the AI-specific ones. Semgrep doesn't catch them. Bandit doesn't either.
# DEAD_DB_RESULT — AI fetched data and forgot to use it
def get_user_stats(user_id):
rows = db.execute("SELECT * FROM events WHERE user_id=?", (user_id,)).fetchall()
return {"status": "ok"} # ← rows is never used
# STUB_SKELETON — AI wrote the function signature and stopped
def process_payment(amount, card_token):
pass # ← production code
# INPUT_OUTPUT_DISCONNECTED — parameters have no effect on return
def validate_email(email):
return {"valid": True} # ← ignores the email entirely
# MISSING_WRITE — save() with no actual INSERT/UPDATE
def save_user(data):
return {"status": "saved"} # ← no DB write happened
These patterns show up in AI-generated code constantly. The model writes a plausible function signature and return value, but the logic in between is missing.
🏗 Design Smells (11 patterns — WARN)
God objects, circular imports, refused bequests, duplicate code blocks — the Martin Fowler classics, caught automatically.
ZIP / Folder Scan — scan your whole project at once
This is the big one. Instead of uploading files one by one:
- Zip your project folder
- Drop it on AINAScan
- Get results for up to 200 files in parallel
Every file gets the full 48-pattern check. The results show:
- Total BLOCK / WARN counts across the project
- Per-file breakdown
- Which files are clean vs. which need attention
Max ZIP size: 50 MB. Free for members (star the GitHub repo to unlock).
What the scan results look like
For each file you get:
1. Pattern checklist — all 48 checks, ✅ PASS / 🔴 BLOCK / ⚠️ WARN per pattern
2. Senior Code Analysis — 7 additional patterns:
-
SILENT_FAILURE— broadexceptthat always returns success -
EMPTY_EXCEPT—except: pass(error swallowed silently) -
DEEP_NESTING— 5+ levels of nested if/for -
PARAM_SHADOW— parameter reassigned inside function -
INCONSISTENT_RETURN— mixedNoneand typed returns
3. Code Structure
- Function count, class count, danger sinks, validators
- Detected libraries (
subprocess,sqlite3,requests...) - Full function list with
SINK/VALIDATORbadges - Mermaid call graph source
4. 🧠 AI Confidence badges on each BLOCK issue
BLOCK SQL_INJECTION_RISK line 47 🧠 98% · L3×6
The 🧠 98% · L3×6 means AINA's Phase 3 causal reasoning engine is 98% confident this is a real vulnerability, backed by 6 L3 causal chain matches from its knowledge base (1.9M+ edges, 133K+ causal relations).
High confidence (≥90%) = red badge. Medium (≥70%) = orange. Below = grey.
What it catches that others miss
Synthetic test cases based on real AI-generated bug patterns:
| Finding | AINAScan | Semgrep (free) | Bandit | Claude inline |
|---|---|---|---|---|
COMMAND_INJECTION (shell=True + user input) |
✅ BLOCK | ❌ | ❌ | ❌ |
COMMAND_INJECTION (f-string in subprocess) |
✅ BLOCK | ❌ | ❌ | ❌ |
PATH_TRAVERSAL (open with user path) |
✅ BLOCK | ⚠️ partial | ❌ | ❌ |
MISSING_WRITE (no INSERT in save fn) |
✅ BLOCK | ❌ | ❌ | ❌ |
FAKE_ASYNC (blocking event loop) |
✅ WARN | ❌ | ❌ | ❌ |
LLM_OUTPUT_INJECTION (AI output → eval) |
✅ BLOCK | ❌ | ❌ | ❌ |
| Interprocedural taint (1-hop) | ✅ BLOCK | ❌ | ❌ | ❌ |
The interprocedural taint tracking is worth calling out — it catches cases where tainted user input passes through a function boundary before hitting a dangerous sink. Most free tools don't do this.
9 languages supported
Python · JavaScript · TypeScript · Go · Ruby · Java · PHP · Kotlin · C/C++
Python gets the deepest analysis (all 48 patterns + senior analysis + structure + AI advisor). Other languages get the core security patterns via tree-sitter AST.
How to use it
Single file:
- Go to AINAScan
- Paste your code or upload a file
- Click Scan
Whole project (ZIP):
- ⭐ Star github.com/Moonsehwan/aina-scan
- Sign in with GitHub (unlocks ZIP scan + scan history + 7-section docs)
- Zip your project, drop it on the ZIP scanner
- Get results for all files in ~10 seconds
Free for members. No code is stored on the server — everything is analyzed in memory and discarded after the response.
7-Section Auto Documentation
Member feature: upload a ZIP and get a Markdown document with:
- Project Structure — file tree + function/class/API counts
- Function Reference — name · line · params · return type
-
Dependencies —
requirements.txtparsed - Mermaid Diagram — module dependency graph
- API Endpoints — FastAPI/Flask auto-detected
- DB Schema — SQLAlchemy Column extraction
- Validation Status — BLOCK/WARN summary per file
Pure AST — no LLM, no API calls, instant.
The benchmark numbers
- P=R=F1=100% on 90-case benchmark (30 TP + 30 TN Python, 30 multilang)
- Zero false positives on top-10 open source repos (10/10 clean)
- 9 languages · tree-sitter AST · deterministic
If you're shipping AI-generated code and want a second opinion before it hits production — give it a try. Takes 5 seconds per file.
Feedback welcome in the comments — especially if you find a false positive or a pattern we're missing.
Top comments (0)