We caught a SQL injection with an offline AI security scanner — here's the exact query it found Sendwave Hub's AI Security Studio, an offline security research platform, detected a classic SQL injection vulnerability in a demo Express app's login endpoint. The platform's deterministic parser and rule engine identified the flaw, with a local LLM explaining the evidence without accessing raw source code or network traffic. The finding, marked as high risk with CWE-89 and CWE-306, demonstrates the tool's ability to run fully offline and provide precise, evidence-based results. Here's a login endpoint from a small Express demo app scan-target-demo-apps/apps/01-sql-injection https://github.com/sendwavehub/scan-target-demo-apps : js app.post '/login', req, res = { const { username = '', password = '' } = req.body; const query = SELECT id, username, email, is admin FROM users WHERE username = '${username}' AND password = '${password}' ; const result = db.exec query ; // ... } ; You've seen this shape before. username and password go straight into the SQL string — no parameter binding, no escaping. Submit admin' -- as the username and anything as the password, and the query becomes: SELECT id, username, email, is admin FROM users WHERE username = 'admin' -- ' AND password = 'anything' -- comments out the rest of the line. The password check never runs. {"ok": true} , logged in as admin . Classic CWE-89, OWASP A03:2021. Nothing novel here — the interesting part is what caught it. We ran this target through AI Security Studio , an offline security research platform we've been building. No cloud calls, no code leaves the machine — everything you're about to read happened on a laptop with no network access to anywhere but localhost:3001 . The important design decision: the LLM never sees raw source code or raw HTTP traffic. The pipeline looks like this: Parser → Rule Engine → Knowledge Retrieval → Summarization → LLM → Reasoning → Finding → Report A deterministic parser and rule engine do the actual finding . The local LLM only explains already-discovered evidence — it's not asked to eyeball a codebase and guess where the bugs might be. If the evidence isn't there, the platform is built to say "Needs Manual Verification" instead of inventing a conclusion. For this run, that meant: http://localhost:3001 as scope. server.js:56 and the missing auth check on the state-changing POST /login route.The generated report includes the actual vulnerable line as evidence, not a generic "possible SQL injection" label: js Source preview. app.post '/login', req, res = { const { username = '', password = '' } = req.body; const query = SELECT id, username, email, is admin FROM users WHERE username = '${username}' AND password = '${password}' ; Risk: High. Root cause: CWE-89 and a separate CWE-306 finding for the missing authorization check . Suggested fix: parameterized queries. Confidence explicitly marked — some findings from this pass are "Confirmed," others are flagged "Needs Manual Verification" rather than asserted, because header/config-level evidence alone doesn't prove exploitability the way a manual Active Test / Repeater run does. It's easy to gloss over "runs locally" as a checkbox feature. In practice it means: The demo app is intentionally vulnerable and open source — safe to point any scanner at, including this one: Built for security researchers, pentesters, and AppSec teams doing work they're authorized to do. Next up in this series: stored XSS — one comment field, every visitor who loads the page.