Back to blog
Guide · Security

Why Giving an AI Agent Direct SQL Access Is Dangerous (and What to Do Instead)

Direct SQL access lets an AI agent leak, corrupt, or delete data in seconds. The real risks, why prompts and read-only roles fall short, and safer patterns.

Claix · Updated November 2026. The real risks of giving an AI agent a database connection, why a prompt and a read-only role fall short, and the safer patterns that work in production. Related: seven gaps in a read-only Postgres role (/blog/read-only-postgres-role-for-ai-agents), how to stop an agent from deleting a database (/blog/how-to-stop-an-ai-agent-from-deleting-your-database), and the PocketOS incident (/blog/pocketos-ai-agent-database-deletion).

The short version

  • Direct SQL access means the agent holds a database connection and writes its own queries.
  • The model is the only gatekeeper. A model can be manipulated, can guess wrong, and can be unpredictable.
  • A prompt is not a permission. Rules in a prompt can be ignored. Privileges in the database cannot.
  • A read-only role helps, and it is not enough. A standard setup on PostgreSQL 16 still has gaps.
  • Reads and changes need different controls: a controlled retrieval layer for reads, and a rules check for INSERT, UPDATE, and DELETE.

What does direct SQL access for an AI agent mean?

Direct SQL access means an AI agent is given a database connection, or a tool that wraps one, and writes the SQL itself. The agent turns a request into a query and runs it. This is how many demos and many text-to-SQL setups work, and how a database MCP server behaves out of the box.

The model decides which tables to query, which columns to read, which rows to change, and when. Whatever the credentials allow, the agent can do.

Why is direct SQL access dangerous?

Nine risks come up again and again.

1. The agent can be manipulated

Instructions hidden in a user message, in a document the agent reads, or in a text field in your own database can change what the agent does. This is prompt injection. Supabase's documentation names it as the main risk of connecting an agent to your data. Classic SQL injection was solved by separating the query from the input. With text-to-SQL, the model writes the whole query as text every time, so there is no fixed shape to protect.

2. A destructive statement takes one call

A DELETE or UPDATE without a WHERE affects every row in the table. A DROP or TRUNCATE removes it. Open-source tools such as SQLGuard MCP exist because agents can accidentally run statements like DELETE FROM users or DROP TABLE orders.

DELETE FROM reservations;
UPDATE orders SET discount_percent = 90;

Both are valid SQL, both run without an error, and neither says anything about intent.

3. A valid query can still be wrong

A query can run, look reasonable, and answer the wrong question. In our own tests, a query that wrote status = 'canceled' instead of 'cancelled' ran fine, matched no rows, and raised no error. A bad join can duplicate rows, and a missing tenant filter can mix customers. Nothing fails, and someone acts on the result.

4. The agent can read what it should not

If the credentials can read a column, the agent can ask for it. A query such as SELECT password_hash FROM users WHERE 1=1 is valid, and the database runs it without complaint. The same goes for data from another tenant when the filter is missing or wrong.

5. Business rules are not database rules

A discount of 90 percent, a balance of minus 99,999, or a status that is not on the approved list are all valid values for their column types. Permissions answer whether a role may touch a table. They do not answer whether this change makes sense for the business.

6. Resources can be abused

A slow or heavy query can hurt a production database. A timeout helps, but a session can often change its own timeout.

7. The output is unpredictable

One run returns a boolean and the next returns a sentence. An automation that expects a fixed shape breaks, and breaks quietly.

8. There is no record

When an answer or a change looks wrong afterwards, you need the question, the statement, and the decision. A raw connection keeps none of that for you.

9. The credentials are the weak point

A token with more authority than the task needs turns any mistake into a large one. In the reported PocketOS incident, a token created for routine operations reportedly carried blanket authority across the provider's API. That incident was an infrastructure call, not an SQL statement, and the lesson transfers: an agent with broad credentials, a destructive action, and no independent check.

Why can't a prompt keep the agent in line?

A prompt can lower the chance of a mistake. It cannot prevent one. The model reads it as text and weighs it with everything else, including its goal and the text it sees along the way. In the PocketOS reports, the agent had safety rules and reportedly acknowledged them only after acting. What stops an action is something the model cannot talk its way past: a database permission, a constraint, or a deterministic check outside the model.

Ordinary permissions answer "may this role touch this table?", not "how much will this statement change?" or "can I undo it?".

Is a read-only database role enough?

No. A read-only role is the foundation, and it is not enough on its own. We ran a standard setup on PostgreSQL 16 and tried to get around it the way a manipulated agent or a careless query would. Six things stood out.

  • The read-only setting is a default, not a lock. default_transaction_read_only = on makes new transactions read-only, and a session can run SET default_transaction_read_only = off. With a role that had write privileges, the write then went through. What stops writes is the absence of the privilege.
  • Timeouts can be switched off. With statement_timeout set to two seconds, a three-second sleep was cancelled, and after SET statement_timeout = 0 it ran to completion.
  • A SECURITY DEFINER function can write for the role. It runs with its owner's privileges, and by default everyone can execute it. In our test, it inserted a row into a table the role could not touch.
  • Table names stay visible. pg_tables listed a table the role had no access to, although its contents stayed protected.
  • SELECT * fails with column-level grants, and the error names the table, not the column.
  • Row-level security with no policy returns zero rows, which fails safe and looks like an empty table.

A role cannot protect what you granted. If it can read a column, a manipulated agent can ask for it. The SQL and the full write-up are in the guide to a read-only Postgres role for AI agents (/blog/read-only-postgres-role-for-ai-agents).

What happens when it goes wrong?

Four patterns cover most incidents.

  • Bulk change. A statement without a precise condition touches every row.
  • Wrong assumption. The agent acts on a guess about scope, such as which environment or tenant it is in, without verifying it.
  • Overreach. The credential allows more than the task needed, so a small mistake has a large effect.
  • Silent error. The query runs, returns something plausible, and is wrong.

The PocketOS incident reportedly combined the second and third. A coding agent working in staging, with a token that reached production, deleted a production volume and its backups in about nine seconds. It was reported as an infrastructure API call. Claix Guard would not have intercepted that specific call. The same failure at the database level is what an independent check is for.

How do you give an AI agent database access safely?

There is no single control. Use layers.

  • Do not give the agent credentials that can do more than the task needs. Use a dedicated role with SELECT on specific columns, and give write credentials only to an executor in your code.
  • Separate staging from production in credentials and accounts, not only in names.
  • Describe your data in plain language, so the agent does not guess.
  • Scope what each agent can use, instead of exposing the whole schema.
  • Return typed answers, not text the next step has to interpret.
  • Check every INSERT, UPDATE, and DELETE against rules before it runs, with a check the model cannot override.
  • Require a person for irreversible actions. That review lives in your workflow, after a denial.
  • Keep backups out of the agent's reach.
  • Log every request and every decision.
  • Test with hostile and mistaken scenarios, not only the happy path.

What are the alternatives to direct SQL access?

  • Predefined functions. You write fixed functions and the agent calls them. This is safe and predictable, and it covers only the questions you wrote code for.
  • A controlled retrieval layer for reads. The agent asks questions and a layer decides which tables and columns can be used, and returns typed answers. The agent never holds a connection.
  • A rules check for changes. The agent proposes an INSERT, UPDATE, or DELETE, and a checker decides whether the rules allow it before anything is executed.
  • Open-source guardrails. Several early-stage projects tackle parts of the problem: a library that checks SQL against a policy file before it runs, an MCP server that classifies queries and asks for confirmation before mutations, a safety layer for Postgres that measures a write before it happens and holds large ones for approval, and a sandbox that validates changes before syncing them. They are worth evaluating. Most are alpha or beta, so check their maturity and limits first.

How does Claix remove the need for direct SQL access?

Claix is a managed control layer between AI agents and your database, with two parts.

Claix Retrieve controls what an agent can read. You connect your database with a read-only role, choose which tables and columns each route can use, and give each agent its own endpoint. The agent asks questions in plain language and gets typed answers back. It never holds a database connection and never writes SQL directly against your tables. Every request is traced. Product: https://www.claix.dev

Claix Guard controls what an agent can change. Before an INSERT, UPDATE, or DELETE runs, your application sends the proposed statement to Claix. Claix checks it against rules you wrote in plain English and approved. It answers allow or deny, with the reason. A denial is still HTTP 200. There is no third verdict. If a change should be reviewed by a person, Guard denies it and your own workflow routes that denial to Slack, email, or n8n. No model decides at check time, and Claix never runs the statement. Your own code does. Product: https://www.claix.dev/guard

Together they replace the dangerous part of direct SQL access: the agent writes the query, and nothing outside the model checks it.

When is Claix not the right choice?

  • You need each end user to see only their own rows inside the tool. Claix scopes access per agent, not per end user. Enforce that with row-level security or in the layer in front of the agent.
  • You only have a handful of fixed questions. A few well-written functions may be all you need.
  • You must self-host everything. Claix is a managed service.
  • You need dashboards, charts, or governed business metrics for analysts.
  • You use a database that Claix does not support yet. Claix supports PostgreSQL, MySQL, and MariaDB.

A checklist before you give an agent database access

  • Create a dedicated role with narrow privileges. Never use a superuser or your application's main database user.
  • Grant SELECT on specific columns, or expose views.
  • Review functions that run with their owner's privileges and revoke public execute access from the ones that write.
  • Set timeouts, and do not give the agent a raw SQL session.
  • Describe your tables and relationships in plain language.
  • Limit what each agent can use.
  • Put a deterministic check before every INSERT, UPDATE, and DELETE.
  • Send irreversible changes to a person after Guard denies them.
  • Keep backups where the agent cannot reach them.
  • Log every request, and test with hostile scenarios.

Sources and further reading

  • Supabase documentation, MCP server (read-only mode, development use, prompt injection): https://supabase.com/docs/guides/getting-started/mcp
  • LangChain documentation, SQL agents and security: https://docs.langchain.com/docs/use_cases/sql/
  • sql-guardrail (open-source SQL policy checker): https://pypi.org/project/sql-guardrail/
  • SQLGuard MCP (open-source MCP safety layer): https://github.com/sealca/sqlguard-mcp
  • Interdict (open-source Postgres safety layer): https://pypi.org/project/interdict-db/
  • SafeAgentDB (open-source sandbox for agent writes): https://pypi.org/project/safeagentdb/
  • MIT AI Incident Database, PocketOS incident: https://airisk.mit.edu/ai-incidents/1469-pocketos-production-database-was-reportedly-deleted
  • PostgreSQL documentation, GRANT: https://www.postgresql.org/docs/current/sql-grant.html
  • PostgreSQL documentation, CREATE FUNCTION and SECURITY DEFINER: https://www.postgresql.org/docs/current/sql-createfunction.html

Claix is a managed control layer between AI agents and your database. Claix Retrieve controls what they can read, and Claix Guard checks every INSERT, UPDATE, and DELETE they propose.

Frequently asked questions

Is it safe to give an AI agent database access?
It can be, if the access is limited and checked outside the model. Use least-privilege credentials, put a controlled layer between the agent and the database, and check every INSERT, UPDATE, and DELETE before it runs. Giving the agent a raw connection with broad privileges is not safe.
What is direct SQL access for an AI agent?
It means the agent holds a database connection, or a tool that wraps one, and writes and runs its own SQL.
Can an AI agent delete my database?
It can delete whatever its credentials allow. A DELETE without a WHERE removes every row in a table, and a DROP removes the table. The credentials, not the prompt, decide how much damage is possible.
What is prompt injection in a database agent?
It is when instructions hidden in a user message, a document, or a database field change what the agent does, for example making it read data or run a statement it was not meant to.
Is text-to-SQL safe for production?
Only with controls around it: a narrow read-only role, a check of every query before it runs, limits on time, rows, and cost, and logs. Without them, a model-written query can be harmful, wrong, or both.
Is a read-only role enough to protect my database from an AI agent?
No. A session can change settings such as the read-only default and the timeout, a function that runs with its owner's privileges can still write, and anything you granted can be read by a manipulated agent.
Can a system prompt stop an agent from running dangerous SQL?
No. A prompt can lower the chance of a mistake, and the model can ignore it or be manipulated around it. Use permissions and deterministic checks that the model cannot override.
How do I stop an AI agent from running DELETE without WHERE?
Give the agent no write credentials, send every change through one executor function, and make that function ask a rules checker first. A rule that every UPDATE or DELETE must name a single row makes a statement without a WHERE get denied. Guard answers allow or deny. It does not return a third verdict.
What is the safest way to let an AI agent read my data?
Use a controlled retrieval layer: a read-only role, a limited set of tables and columns for each agent, and typed answers. The agent asks questions and never holds a connection.
What is the safest way to let an AI agent change my data?
Do not let the agent execute changes. Let it propose them, check each one against rules, and execute only the allowed ones in your own code. Route irreversible denials to a person.
Does Claix run my SQL?
No. Claix Retrieve answers questions from the tables and columns you allow, and Claix Guard only checks the changes your agent proposes. Your own code executes any change, and only after Guard returns allowed: true.
Do open-source guardrails solve this?
They solve parts of it, and some are good starting points. Most are early-stage, and they differ in what they check, where they run, and whether they hold your database credentials. Evaluate each against your needs.