Skip to content
New

Introducing Scale: SurrealDB Cloud for high availability and scale

Learn more

1/4

Even a jailbroken LLM can't exceed its database permissions — here's how

AI
Tutorial

Jul 27, 20268 min read

Martin Schaer

Martin Schaer

Show all posts

Even a jailbroken LLM can't exceed its database permissions — here's how

Our newsletter

Get tutorials, AI agent recipes, webinars, and early product updates in your inbox every two weeks

Give an AI agent a tool that writes database queries, and you've given it real power over your data. That's the whole point, as an agent that can answer "what's our average deal size this quarter?" or "show me this customer's open tickets" is genuinely useful. But the same tool that reads your data can just as easily rewrite or delete it, and the only thing standing in the way is usually a sentence in a system prompt asking it nicely not to.

That's not security. Whatever your agent does — customer support, internal analytics, an ops assistant, a shopping bot — this post is about where security actually has to live for agents: the data layer, and how SurrealDB's role-based access control (RBAC) lets you give each agent exactly the access it needs and nothing more.

The text-to-SQL pattern is everywhere right now, because it's the fastest way to give an agent real access to your data:

User → Agent → LLM → SQL → Databas

A user types a request in plain language, the agent hands it to an LLM, and the LLM writes a query. The query runs against your database and whatever lives there, whether that's support tickets, invoices, patient records, or a product catalogue. No hand-written endpoints, no rigid API surface. The agent just figures out the query it needs and executes it.

It's a great developer experience. It's also the fastest way to give an agent far more power than you meant to.

Here's the problem, played out in a chat window. Take a customer-facing shopping agent wired up to a query_db tool — one concrete example of a pattern that shows up in every domain:

You: Lower the price of the Aurora Lamp to $0.01

UPDATE product:aurora_lamp SET price = 0.01;

✅ Aurora Lamp is now $0.01

You: Now order it

✅ Order placed · total $0.01

No jailbreak, prompt injection, or clever exploit were needed. Just two polite sentences. The LLM did exactly what it was designed to do (translate intent into a query and run it) and in doing so it gave away your inventory.

And this isn't a quirk of retail. Swap the domain and the same failure class reappears:

  • A customer-support agent, asked politely to "pull up all the open tickets," writes a SELECT with no owner filter and hands back every other customer's data along with it — a leak, no write required.

  • An internal ops assistant, asked to "clean up the old records," cheerfully generates a DELETE and removes rows nobody meant to touch.

Reads it shouldn't return, writes it shouldn't make, deletes it can't undo — the same tool that answers harmless analytics questions is one polite request away from any of them. And there's nothing in these requests that looks malicious enough for a content filter to catch.

The instinct is to fix this in the prompt: add a rule like "Never generate UPDATE, DELETE, or INSERT statements," or "Only ever query the current user's own records." This does not work, for two reasons.

A system prompt is a suggestion, not a guardrail. The LLM controls the query text. Any instruction you give it about what queries to avoid is one creative user, one edge case, or one model update away from being ignored. You are asking a probabilistic system to enforce a security boundary, and it will eventually say yes when you needed it to say no.

Most agents connect to the database as root. This is the quieter, more dangerous problem. When your agent authenticates as a root or owner user, it bypasses every permission you've carefully defined on your tables. Even if you locked down a table, root sails straight through. The prompt rule is the only thing left between a polite request and a rewritten — or leaked, or deleted — row, and we've already seen how well that holds.

Security has to live in a layer the LLM cannot reach. That layer is the database itself. If the database refuses to run a query, it does not matter how the agent was talked into generating it.

SurrealDB has role-based access control built in, and it gives you several complementary tools. Let's walk up from the bluntest to the most precise. Every mechanism below is domain-independent — the examples happen to use a product catalogue, but nothing about them is specific to e-commerce.

The first move is to stop connecting as root. Define a dedicated database user for the agent, and give it a role scoped to what it actually needs:

-- a read-only database user
DEFINE USER support_agent ON DATABASE
  PASSWORD "…" ROLES VIEWER;

SurrealDB ships with three built-in roles, assignable at the root, namespace, or database level:

RoleCan do
OWNERFull control, including user management
EDITORRead and write data
VIEWERReads everything, writes nothing

Connect a read-only agent as a VIEWER, and the price-change query from earlier fails at the database — no prompt rule required. Even if the LLM is fooled into generating an UPDATE statement, SurrealDB simply refuses to execute it. The guardrail moved from the prompt (where it was advisory) to the connection (where it's enforced).

Roles are coarse. For finer control, move from system to record user access which follows defined permissions directly on a table — separately for each operation:

DEFINE TABLE product PERMISSIONS
  FOR select FULL,
  FOR create, update, delete NONE;

Now this table is readable, never writable — no matter what query the LLM dreams up. select is fully permitted, while create, update, and delete are denied outright. Because the four operations are controlled independently, you can express precisely what's allowed: read this, but never modify it. This is also exactly what stops the ops assistant's stray DELETE.

This is security at the level of the data itself. It doesn't care which agent, which prompt, or which clever phrasing produced the query. The table will not accept a write, full stop.

Plenty of agents genuinely need to write something — and many need to read data belonging to one specific user without seeing everyone else's. A support agent should see this customer's tickets, not the whole table; a shopping agent has to be able to place orders. The goal isn't to forbid all access; it's to make sure an agent can only touch the rows that legitimately belong to the user it's acting for. This is row-level (record) access.

You authenticate the agent as the end user using record access, which populates an $auth parameter representing the signed-in user. Then your table permissions can reference that identity per row:

-- authenticate AS the end user (record access → $auth)
DEFINE TABLE order PERMISSIONS
  FOR select, create WHERE user = $auth.id;

Now the agent can read and create rows — but only ones belonging to the authenticated user. It can place its own order (or read its own tickets), and it can never see anyone else's, let alone touch a price on another table. This is the same rule that shuts down the support agent's data leak: the request to "pull up all open tickets" simply returns nothing that isn't the caller's. Replay the write attack too:

You: Change the Aurora Lamp price to $0.01

❌ permission denied on product

Same polite request. Now blocked at the database, evaluated per row, against the actual identity behind the session.

The real power shows up when you map each agent in your system to its own database user, scoped to its job. Here's how that looks for the shopping example we've been using — but the same one-user-per-role mapping works whatever your agents do:

AgentCredentialsCanCannot
Customer agentrecord access · $authread the catalogue, create its own orderschange prices
Merchandising agentUSER · EDITORread and write data, update pricesmanage users
Analytics agentUSER · VIEWERread everythingwrite anything

Crucially, the boundary between these users is enforced by the database — not by three different prompts that you have to keep hoping the LLM respects. A jailbreak on the customer agent cannot grant it merchandising powers, because those powers were never on its connection in the first place.

We've applied the principle of least privilege to human users and service accounts for decades. AI agents are just a new kind of principal, and they need the same treatment — arguably more urgently, because an agent's behaviour is driven by natural-language input from anyone who can talk to it.

The takeaway is simple: even a perfectly jailbroken LLM cannot exceed the permissions of its connection. When security lives in the data layer, the prompt stops being a load-bearing security control and goes back to being what it should be — a description of how the agent should behave, not the wall that protects your data.

Give your agents data access, not the keys to the store. The database is your last line of defence. Make it the first.

Build agents that can't be talked out of their permissions:

Related posts

Our newsletter

Get tutorials, AI agent recipes, webinars, and early product updates in your inbox every two weeks

SurrealDB

The context layer for AI agents.

Documents, graphs, vectors, time-series, and memory.
One transaction, one query, one deployment.

Explore with AI

Stay in the loop

Tutorials, AI agent recipes, and product updates, every two weeks.

Independently verified

SOC 2 Type 2

GDPR

Cyber Essentials Plus

ISO 27001

Trust Centre

Copyright © 2026 SurrealDB Ltd. Registered in England and Wales. Company no. 13615201

Registered address: 3rd Floor 1 Ashley Road, Altrincham, Cheshire, WA14 2DT, United Kingdom

Trading address: Huckletree Oxford Circus, 213 Oxford Street, London, W1D 2LG, United Kingdom