Portfolio by Johnny RiceInformatics demo
ClariTrial
All posts

SQL Injection in the Age of AI: When Language Models Write Your Queries

Letting an LLM generate arbitrary SQL is the new injection vector. Allowlisted presets and validated parameters close the gap without losing flexibility.

SQLsecuritydatabases

SQL injection has been a top-ten web vulnerability for over two decades. The classic version is well understood: a user types '; DROP TABLE users; -- into a form field, and a poorly written backend interpolates it into a query string. Parameterized queries solved this for human input.

But language models are not human input. They sit inside the trust boundary, and when you ask a model to generate SQL, you are giving it the same power as a developer with database access. The model does not need to be malicious. It just needs to be wrong in the right way.

The new attack surface

When an AI agent generates SQL from natural language, several risks emerge:

  1. Data exfiltration: the model might generate a query that joins across tables the user should not have access to, or that returns PII columns that were not part of the original question.
  2. Resource exhaustion: a poorly constructed query (missing WHERE clause, cartesian join, full table scan on a large table) can lock up the database or consume expensive compute.
  3. Schema leakage: the model might reveal table names, column names, or relationships in its response text, giving an adversary reconnaissance information.
  4. Prompt injection via data: if the database contains user-generated text, a SELECT that returns that text to the model could include prompt-injection payloads that alter the model's behavior on the next turn.

Traditional SQL injection defenses (parameterized queries, WAFs, input sanitization) do not apply cleanly here, because the "input" is not a user string. It is a query written by a model that has been given schema information and asked to be helpful.

ClariTrial's two-tier approach

ClariTrial does not let the model write free-form SQL. Instead, it provides two controlled access paths:

Tier 1: Allowlisted presets

queryAactPreset offers four curated queries: protein degrader trials, molecular glue trials, kinase inhibitor trials, and a combined recruiting-trial slice. Each preset is a fixed SQL template. The model selects which preset to call; it does not modify the query. The result schema is known, the columns are safe, and the query cost is bounded.

This handles the most common question patterns (phase breakdowns, sponsor leaderboards, trial counts by modality) with zero SQL generation.

Tier 2: Validated parameterized queries

queryAactFlexible accepts structured filter parameters: target gene, sponsor name, drug name, condition, phase, and modality. The system builds safe parameterized SQL from these filters. The model provides the filter values; the system writes the SQL.

The generated SQL is logged in the audit trail alongside the result count, so operators can review what was executed. If no substantive filter is provided (the model tries to select everything), the tool rejects the request.

Fail-safe behavior

If AACT database credentials are missing or the connection fails, both tools return ok: false. The orchestrator prompt tells the lead model to say so and fall back to the ClinicalTrials.gov API, not to improvise SQL or make up results.

Why this matters for PII-bearing systems

Healthcare databases contain protected health information. Financial databases contain transaction records and account details. HR systems contain salary data and performance reviews. In all of these domains, letting an LLM generate arbitrary SQL is equivalent to giving an untested contractor unrestricted database access.

The preset-plus-parameter pattern offers a middle path:

  • Presets for high-frequency, well-understood queries. No SQL generation at all.
  • Parameterized queries for flexible but bounded access. The model provides filter values; the system writes the SQL. The surface area the model controls is the content of WHERE-clause parameters, not the query structure.
  • Audit logging of generated SQL so that even parameterized queries can be reviewed after the fact.

This pattern does not require giving up natural-language flexibility. Users still ask questions in plain English. The agent still interprets those questions and decides which tool to call. But the moment the question touches a database, the agent's role shifts from "query author" to "parameter provider," and the system handles the rest.

The residual risk

No approach is zero-risk. A model could provide filter values that are technically valid but semantically misleading (searching for a drug name that happens to match an unrelated condition). The parameterized query would execute correctly but return irrelevant results. This is a data-quality issue, not a security issue, and it is addressed by the answer-structure layer (Facts/Summary/Interpretation headings) that makes the raw query results visible to the user.

The goal is not to make SQL access perfectly safe. It is to shrink the attack surface from "the model can write any SQL" to "the model can choose presets and provide filter values," which is a dramatically smaller and more auditable surface.