DEV Community

jomynn
jomynn

Posted on

We caught a SQL injection with an offline AI security scanner — here's the exact query it found

The bug

Here's a login endpoint from a small Express demo app
(scan-target-demo-apps/apps/01-sql-injection):

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);
  // ...
});
Enter fullscreen mode Exit fullscreen mode

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'
Enter fullscreen mode Exit fullscreen mode

-- 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.

What actually 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
Enter fullscreen mode Exit fullscreen mode

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:

  1. Point the scanner at http://localhost:3001 as scope.
  2. Let it run a real passive crawl — no exploitation, just discovery.
  3. Run a source scan against the target's own directory.
  4. The rule engine flags the string-concatenated query pattern in 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:

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}'`;
Enter fullscreen mode Exit fullscreen mode

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.

Why "offline" is the actual point

It's easy to gloss over "runs locally" as a checkbox feature. In practice it means:

  • You can point it at unreleased/internal code without a vendor's cloud pipeline ever touching it.
  • The rule engine — not the LLM — does secret detection, JWT/header/cookie analysis, and pattern matching, so results are reproducible and don't drift between runs.
  • The LLM's job shrinks to something it's actually reliable at: turning structured findings into a clear explanation, not hunting for vulnerabilities in raw text.

Try it yourself

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.

Top comments (1)

Collapse
 
alexshev profile image
Alex Shev

Offline scanning is underrated for security workflows because it changes the adoption story. Teams can inspect the finding without first accepting a cloud trust boundary. The next useful layer is evidence quality: exact source path, tainted input path, and a minimal repro that a human can verify quickly.