Skip to content

Read-only enforcement

The reasoning behind this is in read-only by design. This is the mechanism.

Every query is parsed before execution. Only statements whose first token is one of these are permitted:

SELECT
WITH
EXPLAIN
SHOW
TABLE
VALUES

Anything else is refused. INSERT, UPDATE, DELETE, DROP, ALTER, TRUNCATE, CREATE, GRANT, and REVOKE do not reach the database.

One statement only. A second statement appended after a semicolon is rejected, so SELECT 1; DROP TABLE x does not run the first half either.

The check is on the parsed statement, not on string matching — a comment or odd whitespace does not get around it.

SurfaceLimit
ChatRow-limited result set
Data Explorer playground200 rows
Column sampling20 distinct non-null values, one column

A careless SELECT * cannot pull a warehouse into memory.

The queries SEMANTIX builds — introspection, sampling, exploration — quote schema, table, and column names. A column named users; DROP TABLE x is a column name, not an injection.

Chat-generated SQL passes an AST validator and a dry-run gate before it is executed. A query that fails is refused with a structured reason rather than run optimistically, and the validated SQL is shown in the thread so you can see what actually ran.

LimitValue
Stored result sample25 rows
Stored result length8000 characters
Sampling cache~1 minute per column

The allowlist governs the in-product SQL path only. These run outside it:

Their permissions are whatever the credentials or endpoint enforce. Use a read-only database role for them.

The enforcement makes SEMANTIX unable to write. A read-only database role makes it unable to write even if enforcement failed, a credential leaked, or something else went wrong. Both are cheap; set both.