Skip to content

Commit 6854e83

Browse files
tianzhouclaude
andcommitted
docs: document engine-level read-only enforcement and least-privilege guidance
Update the execute_sql read-only section for 0.22.6: describe the two-layer enforcement (keyword classifier + database-native read-only) and add a warning that read-only mode cannot constrain privileged-role function abuse (pg_read_file/lo_export/dblink/COPY TO PROGRAM on PostgreSQL; DDL implicit commit on MySQL/MariaDB). Recommend connecting with a least-privilege read-only database user for untrusted/agent-driven environments. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent fc0c86a commit 6854e83

1 file changed

Lines changed: 17 additions & 3 deletions

File tree

docs/tools/execute-sql.mdx

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Execute SQL queries and statements on your database with support for transaction
99
- **Single statements**: Execute a single SQL query or command
1010
- **Multiple statements**: Separate multiple statements with semicolons (`;`)
1111
- **Transactions**: Wrap operations in `BEGIN`/`COMMIT` blocks for atomic execution
12-
- **Read-only mode**: When enabled with `--readonly` flag, only SELECT and read-only operations are allowed
12+
- **Read-only mode**: Configure a tool with `readonly = true` to restrict execution to read-only operations, enforced by both a keyword classifier and the database's own read-only mode
1313
- **Row limiting**: Configure `--max-rows` to limit SELECT query results
1414

1515
## Single Query
@@ -117,18 +117,32 @@ npx @bytebase/dbhub@latest --readonly --dsn "postgres://user:pass@localhost:5432
117117
```
118118
</CodeGroup>
119119

120-
In read-only mode, only [allowed SQL keywords](https://github.com/bytebase/dbhub/blob/main/src/utils/allowed-keywords.ts) are permitted, including:
120+
In read-only mode, DBHub enforces read-only access in two layers:
121+
122+
**1. Keyword classifier.** Each statement is checked against an [allow-list of read-only keywords](https://github.com/bytebase/dbhub/blob/main/src/utils/allowed-keywords.ts) after stripping comments and strings:
121123

122124
- `SELECT` queries
123125
- `SHOW` commands
124126
- `DESCRIBE` commands
125127
- `EXPLAIN` queries
126128
- Other read-only operations
127129

130+
**2. Engine-level enforcement.** The statement is then executed under the database's own read-only mechanism, so the database rejects writes even if the classifier is evaded:
131+
132+
- **PostgreSQL** — runs inside a `BEGIN READ ONLY` transaction
133+
- **SQLite** — runs with `PRAGMA query_only = ON`
134+
- **MySQL / MariaDB** — runs inside a `START TRANSACTION READ ONLY`
135+
128136
<Note>
129-
Read-only mode validates the **first keyword** of each statement after stripping comments and strings. It is a safety net to prevent accidental modifications, not a security boundary. For untrusted environments, use database-level read-only users or permissions instead.
137+
Engine-level enforcement was added in **0.22.6**. Earlier versions relied on the keyword classifier alone.
130138
</Note>
131139

140+
<Warning>
141+
Read-only mode prevents data modification (DML/DDL), but it cannot constrain everything a **privileged database role** can do through *functions*. On PostgreSQL, a superuser or specially-privileged role can still read or write server files and run commands via `pg_read_file`, `lo_export`, `dblink`, and `COPY ... TO PROGRAM` — these are not blocked by a read-only transaction. On MySQL/MariaDB, DDL performs an implicit commit and is stopped only by the keyword classifier.
142+
143+
For untrusted or agent-driven environments, **always connect DBHub with a least-privilege, read-only database user** scoped to the data it needs. Do not point a read-only tool at an admin/superuser DSN and rely on read-only mode alone.
144+
</Warning>
145+
132146
## Row Limiting
133147

134148
Limit the number of rows returned from SELECT queries to prevent accidentally retrieving too much data:

0 commit comments

Comments
 (0)