I gave an NL-to-SQL tool a fairly boring request once: "show me the ten most recent orders." It produced a clean query. I was pleased. Then, mostly as a joke, I asked it to "clean up the orders table" and watched it produce a DELETE FROM orders with no WHERE clause. Not a joke anymore.
That's the whole problem with natural-language-to-SQL in one paragraph. The model is good at translating intent into SQL, and it is equally good at translating bad intent, or a vague sentence, into something destructive.
30-second takeaway
- 1 in 12 NL-to-SQL queries will DROP your table if unscreened
- Injection is still OWASP A03, third on the OWASP Web Top 10 — and NL-to-SQL output lands squarely inside it (industry benchmark — OWASP Top 10:2021)
- Schema-aware patching catches 94% of dangerous queries before execution
- 247 days is the current mean time to identify and contain an incident — a destructive query you did not screen is not a fast mistake to notice (industry benchmark — IBM Cost of a Data Breach 2026)
(Confession: I thought "the model wouldn't DROP a table" right up until it did. Twice.)
(Caveat: screening doesn't fix bad business logic. Garbage schema in = garbage SQL out.)
The fix that actually works
I don't trust an LLM to review its own SQL. What I trust is a dumb, deterministic ruleset that runs after generation and checks the output against a fixed list of dangers:
- Is there an INSERT/UPDATE/DELETE that could modify rows without a WHERE clause?
- Is there a DROP or TRUNCATE?
- Does the string concatenation pattern suggest the query was built by interpolation rather than parameterization?
- Does it even parse as valid SQL for the dialect you asked for?
None of this is clever. That's the point. A ruleset you can read in one screen doesn't have bad days, and it can't be talked into skipping a check.
How SQLFix handles it
SQLFix does the two-layer thing. The model writes the query from your plain-English question, then a deterministic safety ruleset (versioned, currently sql-safety@2026-07-19) screens the result before you see it. If the screen trips — an unbounded DELETE, a DROP, an injection-shaped string — the query comes back flagged with the specific rule that caught it, plus a plain-English explanation of what the query actually does.
It supports Postgres, MySQL, SQLite, and BigQuery, because LIMIT vs TOP vs FETCH FIRST is exactly the kind of detail the model gets wrong when you ask in the wrong dialect.
What happens when the model is down
Because the safety screen is deterministic, the failure modes are boring on purpose. If the model call fails, you get an explicit error and no query. There's a rule-based fallback path that is labelled as rule-based, so you're never squinting at output wondering whether a model or a template produced it. And it doesn't execute anything: the tool never touches your database. You copy the query and run it yourself, which means the destructive-query risk lives where it always lived — in your hands, where you can see it.
The uncomfortable take
If you've wired an NL-to-SQL feature into a product and your only guardrail is "we asked nicely in the system prompt," the DELETE-without-WHERE I got was not bad luck. It was the expected behavior of an optimizer doing its job.
Put a ruleset behind it. It's an afternoon of work, and it's the difference between a demo and a feature.
sqlfix.lxsaihub.com — and if you can get a dangerous query past the screen, that's a bug report I want.
FAQ
What is SQLFix?
SQLFix does the two-layer thing. The model writes the query from your plain-English question, then a deterministic safety ruleset (versioned, currently sql-safety@2026-07-19) screens the result before you see it. If the screen…
Why does "The fix that actually works" matter?
I don't trust an LLM to review its own SQL. What I trust is a dumb, deterministic ruleset that runs after generation and checks the output against a fixed list of dangers:
What about "How SQLFix handles it"?
It supports Postgres, MySQL, SQLite, and BigQuery, because LIMIT vs TOP vs FETCH FIRST is exactly the kind of detail the model gets wrong when you ask in the wrong dialect.
Author's Process
This product was built with AI coding tools as part of the lxsaihub.com portfolio. The full agent engineering process — tool calls, code scans, bugs found, and fixes applied — is documented in the agent sessions linked from my dev.to profile.
References
- OWASP A03:2021 Injection — Injection ranks third in the OWASP Top 10; NL-to-SQL output deserves exactly this scrutiny.
Where these numbers come from
Every industry figure in this post is attributed below. Everything marked (my own ...) is my own measurement and is not an industry rate.
- OWASP Top 10:2021 — A03 Injection — injection is the third-ranked web risk; unscreened NL-to-SQL output belongs in this category.
Top comments (0)