Read-Only AI Analytics: Architecture, Controls, and Threat Model
What read-only AI analytics actually requires: the threat model, the control layers that enforce it, and the residual risks a security review should probe.
By the Datarelix Team · Published · Updated · Last verified
Read-only AI analytics means an AI system can answer questions from your database but has no path — accidental or adversarial — to change it. That property cannot be asserted in a prompt; it has to be enforced at independent boundaries: the database identity, a validator that parses every query, a separated execution layer, an isolated network path, and a recorded trace.
Who this assessment is for
Security engineers and IT reviewers running a vendor assessment on a conversational analytics tool. Database and data-platform owners deciding what credential to hand over and what it should be allowed to see. Data leaders who need to answer “what happens when the model goes wrong?” with a mechanism rather than a reassurance.
How to stop an AI tool from writing to your database
Plenty of tools claim read-only behavior because a system prompt tells the model not to write. A prompt cannot enforce that. Models can be steered by adversarial input, and injected instructions arrive through the same channel as legitimate ones. Read-only by design means something stricter: even if the model proposes a write, no component downstream will execute it.
A structured plan is the model’s only output, and it executes nothing by itself. The execution layer validates that plan against a strict schema and runs each step. The read-only validator rejects any generated query that is not a read. The isolated query service is the only component holding the database connection.
The threat model
Five threats cover most of what a security review of this category needs to probe.
| # | Threat | Vector | What failure looks like |
|---|---|---|---|
| T1 | Prompt-injection-driven write attempt | Adversarial text in a question, or in curated table descriptions, steers the model into proposing a mutating statement | The system executes a write the user never intended |
| T2 | Destructive SQL | The model emits DROP, DELETE, TRUNCATE, or DDL — hallucinated or induced | Data loss or schema damage in the connected database |
| T3 | Exfiltration via generated analysis code | Generated Python tries to send query results to an external host | Result data leaves the environment over the network |
| T4 | Credential exposure to the model | A crafted prompt coaxes connection details into a model response | Connection strings or secrets surface in conversation |
| T5 | Cross-account access | A request from one account reaches another account’s connections, runs, or dashboards | One customer’s data is visible to another |
T1 and T2 differ in intent — one adversarial, one a model error — but converge on the same choke point.
The control layers
Least-privilege database identity
The first control belongs to you, not the vendor: what the connected credential is allowed to do. A read-only analytics tool should be connected with a database user granted SELECT on the schemas you want to ask about and nothing else — the per-engine connection guides show the grants for each engine. On Azure SQL, Databricks SQL, and Kusto, Enterprise arrangements can instead run a connection with the signed-in user’s own database permissions (per-user On-Behalf-Of), so each person’s questions are bounded by the access they already hold. Because the database engine enforces this layer, it does not depend on anything in the AI system behaving correctly.
A read-only validator that parses, not pattern-matches
Every generated SQL statement is parsed into a full syntax tree before it runs, and rejected unless it is a read: SELECT statements, CTEs, and set operations only. Parsing matters because keyword filters fail on real SQL. Consider a data-modifying CTE, written here against a fictional retailer’s demo schema:
-- Looks like a read to a keyword filter. It is a write.
WITH removed AS (
DELETE FROM orders
WHERE status = 'test'
RETURNING order_id
)
SELECT COUNT(*) FROM removed;
A filter that checks whether the statement “starts with SELECT or WITH” waves this through. A syntax-tree walk finds the DELETE node inside the CTE and rejects the whole statement. KQL and ES|QL do not share SQL’s grammar, so each goes through a dedicated validator that blocks every mutating or administrative command. Automatic row limits are applied to every query, so no single question can return an unbounded result. Against T1 and T2 this is the choke point: a non-read has no execution path.
Plan/execute separation
The model returns a structured plan and executes nothing. The execution layer validates that plan against a strict schema, then runs each step itself. A plan is inert data: it can be inspected, rejected, and recorded before anything touches a database. Because execution authority never sits with the model, prompt injection can change at most what is proposed, never what is permitted. Each run is recorded step by step and reopenable from history, so a reviewer can check exactly what ran.
An isolated query service holds the connection
Validated queries run in an isolated query service, the only component with the database connection. Credentials are encrypted at rest and decrypted only at the moment a query executes, held by the execution layer. The model never receives them, so there is no connection string in its context to extract. That closes T4 structurally rather than behaviorally, and the full argument is in how credentials stay out of the model.
A no-network sandbox for generated Python
Questions that need more than SQL — a forecast, a cohort breakdown — run generated Python in an isolated sandbox with no network access: egress blocked at the network layer (a firewall, not a code-level check), under hard CPU and memory caps. Code that tries to send results anywhere fails at the socket. That is the control for T3: exfiltration needs a network path, and there is none.
Mapping controls to threats
A useful property to demand of any architecture in this category: every threat should be covered by at least two independent layers, so no single failure is sufficient on its own.
| Threat | Primary control | Independent backstop |
|---|---|---|
| T1 Prompt-injection write attempt | Read-only validator rejects non-reads | Plan/execute separation; read-only database identity |
| T2 Destructive SQL | Read-only validator (full syntax tree) | Read-only database identity refuses at the engine |
| T3 Exfiltration via analysis code | No-network sandbox (network-layer egress block) | Raw query results are never passed back to the model; CPU/memory caps |
| T4 Credential exposure to the model | Credentials held only by the execution layer | Encryption at rest; decryption only at query execution |
| T5 Cross-account access | Every record scoped to the requesting account in every query | Database row-level security |
Account scoping is enforced by the execution layer on every record it touches, with database row-level security as the backstop beneath it.
Residual risks a review should probe
Three risks remain after every layer above.
The connected credential’s scope is your responsibility. The platform can read whatever the credential you connect can read. Connect a broad account and questions range over everything it sees — validation still restricts execution to reads, but a read of data you never meant to expose is still exposure. A scoped, read-only database user is a control only you can apply.
A single answer value can carry into follow-up context. Raw query results — the result tables — are never passed back to the model. But a single-row answer value, say one revenue figure, can be carried into follow-up conversation context so that “and how does that compare to last year?” makes sense. A review done at depth should pin the boundary exactly: schema structure and single answer values, not result tables.
Ambiguous questions can be misread. “Active customers” by last sign-in and “active customers” by recent purchase are different queries, and the model must commit to one reading. The exact query ships with every answer, so a misread is visible in one glance.
Questions to ask any vendor
Six questions separate enforced read-only from asserted read-only. They preview the the AI analytics security checklist, which expands each into pass/fail criteria.
- Is read-only enforced by parsing every statement into a syntax tree, or by keyword filters and prompt instructions?
- Does the model ever hold credentials or a live database connection, even transiently?
- What exactly from my database enters the model’s context — structure only, or sample values and result rows?
- Can generated analysis code reach the network, and is that enforced in code or at the network layer?
- For every answer, can I see the exact query that executed and the source tables it touched?
- What enforces that nothing crosses account boundaries?
The same pipeline, on Datarelix
Datarelix runs the five layers above as described, against any engine it supports and ideally with a read-only credential you scope yourself. The model receives the question plus schema structure and returns a structured plan; the execution layer validates it, and the pipeline runs stage by stage. The canonical statement of every boundary is on the security page.
Where read-only controls stop helping
If your use case requires writing to the database — building tables, upserting model scores, running transformations — a read-only analytics layer is the wrong tool by definition, and Datarelix has no write path to offer.
Read-only controls bound the blast radius of a wrong answer. They do not make answers correct. Confirming that an ambiguous question was read as intended remains a human step, and the evidence trail exists to make that step fast rather than to remove it.
A review that stops at the execution boundary also stops short. The three residual risks above are the ones that survive every layer, and the first of them is yours to close, not ours.
Notes and provenance
Product statements describe Datarelix as shipped in August 2026; the security page is canonical. The SQL example uses a fictional retailer’s demo schema and is illustrative rather than output from a live system. The threat table is our own framing rather than a published taxonomy, and no external sources are cited.
Read the security page, then check one answer
Read the security overview for the boundary-by-boundary account. Then connect a database, ask one question, and confirm that the query shown is a read and that its source tables are the ones you expected.