Safeguard
AI Security•

Can prompt injection make an LLM produce SQL injection?

Yes, if an app runs model-written SQL unchecked. Use parameterized queries, a read-only database role, allowlists, and treat model output as untrusted.

Safeguard Security Team
5 min read

Yes. If an application lets a language model write SQL and then runs that SQL, an attacker who can influence the model's input, directly or through a document it reads, can steer the output toward harmful queries. The defence is architectural: never execute model output as trusted, and limit what the database account can do.

How does the chain work?

Two weaknesses combine. The first is prompt injection: the model cannot reliably separate instructions from data, so text in a user message, a web page or a record can alter what it does. The second is improper output handling. OWASP's entry on improper output handling lists, among its examples, LLM-generated SQL queries executed without proper parameterization, leading to SQL injection. It also describes output entered into a shell, or JavaScript returned to a browser, as the same kind of mistake.

The model is not the vulnerability in the database. The application's trust in the model is. This post stays on defence and does not give attack strings.

Where does this pattern appear?

"Ask your data" features, text-to-SQL assistants, reporting bots and agents with database tools are common. The user types a question, the model produces a query, the application runs it and shows the result.

The attacker's text can arrive indirectly. A customer comment stored in a table, later summarised by the same assistant, can contain instructions. The model sees it in context along with the legitimate request. This is why protection cannot rely on checking only what the user typed.

What defences work?

Remove the need for free-form SQL where you can. Offer a fixed set of parameterized queries or stored procedures. Let the model choose which one and fill in values, and validate those values by type and range. This is the strongest approach.

Use parameterization for any values. If the model supplies values, bind them as parameters. Never concatenate them into query text.

Constrain the database account. Use a dedicated role with read-only access to a narrow set of views. No access to credentials tables, no writes, no schema changes, no administrative functions. If the model's query is hostile, the database refuses.

Validate generated SQL before running it. Parse it and allow only a single statement of the expected type against allowed tables and columns. Reject everything else. Validation is a second layer, not a replacement for least privilege, since parsers and models both make mistakes.

Limit blast radius. Set query timeouts, row limits and rate limits, and run against a replica for analytics.

Keep untrusted data apart. Mark retrieved or user-supplied text as data, and avoid giving the same model both untrusted content and powerful tools in one step.

Log and review. Record the question, generated query, result size and who asked. Alert on queries that touch unexpected tables.

OWASP's guidance for this class of risk is to treat the model like any other user, adopting a zero-trust approach, and to validate responses before they reach backend functions, following ASVS guidance on input validation and context-aware output encoding.

A constructed example

A reporting assistant converts questions into SQL against a sales database. In version one it connects as a database owner and runs whatever comes back. A malicious note stored in a customer record tells the assistant, when it summarises, to list another table. The query runs, since the owner role can read everything.

In version two, the assistant uses a role limited to two read-only views. Queries pass through a parser that allows one SELECT on those views with a row limit of 1,000. The same note produces a rejected query and a log entry, and the user sees an error.

How to check or apply this

  1. List every place a model's output reaches a database, shell, browser or API.
  2. Replace free-form SQL with parameterized queries or approved templates where possible.
  3. Give the model's database role the smallest read-only scope, on views, not base tables.
  4. Parse and validate any generated SQL: single statement, allowed type, allowed objects.
  5. Add timeouts, row caps and rate limits.
  6. Separate untrusted content from tool-using steps, and require approval for risky actions.
  7. Log queries with the user and the source documents in context, and alert on anomalies.
  8. Test with a harmless canary: put an instruction in a stored record and confirm it cannot change what the assistant runs.

Quick check

Is a stricter system prompt a sufficient fix?

No. Prompts can be bypassed. Enforce limits in code and database permissions, which do not depend on the model complying.

Does parameterization solve everything?

It stops values from altering query structure. If the model writes the structure itself, you also need allowlists, validation and a restricted database role.

Sources

Last reviewed: 18 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.