SQL Safety Reference
SQL Safety Reference
Section titled “SQL Safety Reference”dbward processes every SQL statement through three safety layers before execution:
- Classification — determines the operation type
- Review — checks for risky patterns
- Risk scoring — calculates overall risk level for auto-approve decisions
SQL Classification
Section titled “SQL Classification”Every statement is classified into one of three categories:
ExecuteSelect (read-only)
Section titled “ExecuteSelect (read-only)”SELECTSHOWEXPLAIN(without ANALYZE)EXPLAIN ANALYZEon SELECT statementsSET(safe session variables only)
ExecuteDml (write operations)
Section titled “ExecuteDml (write operations)”INSERT,UPDATE,DELETE,MERGECOPYCALL(stored procedures)CREATE TABLE,CREATE VIEW,CREATE INDEXALTER TABLESELECTwith writable CTE (WITH ... INSERT/UPDATE/DELETE)SELECTwith dangerous functions (24 known functions)EXPLAIN ANALYZEon DML statements (actually executes the inner statement)SELECT INTO
DestructiveDdl (subcategory of ExecuteDml)
Section titled “DestructiveDdl (subcategory of ExecuteDml)”These statements are classified as ExecuteDml but flagged as DestructiveDdl. They pass through the classifier and are controlled by sql_review rules:
DROP TABLE¹DROP VIEW¹DROP INDEX¹DROP SEQUENCE¹TRUNCATE¹CREATE SEQUENCE¹
¹ Requires Permission::RequestDdl (request.ddl). Controlled by sql_review rules (default: block for drop_table/truncate, warn for others). --allow-ddl bypasses sql_review blocks. See Break-Glass.
Rejected (blocked by default)
Section titled “Rejected (blocked by default)”DROP SCHEMA/DATABASE/FUNCTION/ROLECREATE FUNCTION/PROCEDURE/TRIGGER/ROLE/DATABASEGRANT,REVOKEBEGIN,COMMIT,ROLLBACK,SAVEPOINTLOCK TABLELOAD DATASET(unsafe variables)
Special rules
Section titled “Special rules”| Condition | Result |
|---|---|
| Parse failure | Classified as ExecuteDml (fail-closed: requires approval) |
| Unknown statement type | Classified as ExecuteDml |
| Input > 1 MB | Rejected |
| > 100 statements | Rejected |
| Multiple SELECT statements | Rejected (use single SELECT) |
SET + SELECT combo | Allowed |
| NULL bytes in input | Rejected |
SQL Review (14 rules)
Section titled “SQL Review (14 rules)”Each rule has a configurable severity: warn, block, or off.
block(default forno_where_delete,no_where_update,drop_table,truncate) — rejects the request regardless of workflow (DDL rules ² can be bypassed with--allow-ddl)warn(default fordrop_column,not_null_without_default,create_index_not_concurrently,alter_column_type,mixed_ddl_dml,large_in_list,drop_index,drop_view,drop_sequence) — adds a finding to the risk assessmentoff(default forcreate_sequence) — rule is disabled
[[sql_review]]database = "*"environment = "development"no_where_delete = "warn"no_where_update = "warn"drop_table = "warn"drop_column = "warn"not_null_without_default = "warn"create_index_not_concurrently = "warn"alter_column_type = "warn"truncate = "warn"mixed_ddl_dml = "warn"large_in_list = "warn"drop_index = "warn"drop_view = "warn"drop_sequence = "warn"create_sequence = "off"Rule descriptions
Section titled “Rule descriptions”| Rule | Fires when | Risk |
|---|---|---|
no_where_delete | DELETE without WHERE clause | Entire table deletion |
no_where_update | UPDATE without WHERE clause | Entire table overwrite |
drop_table | DROP TABLE detected | Permanent data loss |
drop_column | ALTER TABLE DROP COLUMN | Column data loss |
not_null_without_default | ALTER TABLE ADD COLUMN NOT NULL without DEFAULT | Fails on existing rows |
create_index_not_concurrently | CREATE INDEX without CONCURRENTLY (PostgreSQL) | Table lock during build |
alter_column_type | ALTER COLUMN ... TYPE | Table rewrite, potential data loss |
truncate | TRUNCATE TABLE | All data removed |
mixed_ddl_dml | DDL and DML in same request | Complex rollback |
large_in_list | IN (...) with > 100 values | Performance concern |
drop_index | DROP INDEX detected | Index removal, query performance impact |
drop_view | DROP VIEW detected | View removal, dependent queries break |
drop_sequence | DROP SEQUENCE detected | Sequence removal, ID generation impact |
create_sequence | CREATE SEQUENCE detected | New sequence creation |
² DDL rules (drop_table, drop_column, truncate, create_index_not_concurrently, alter_column_type, not_null_without_default, drop_index, drop_view, drop_sequence, create_sequence) can be bypassed with --allow-ddl. DML safety rules (no_where_delete, no_where_update, large_in_list) and mixed_ddl_dml are never bypassable.
Risk Scoring
Section titled “Risk Scoring”Risk scoring determines whether a request qualifies for auto-approve.
Levels
Section titled “Levels”| Level | Numeric | Meaning |
|---|---|---|
| Low | 1 | Safe (SELECT, safe DDL, small tables) |
| Medium | 2 | Moderate concern |
| High | 3 | Significant risk |
| Critical | 4 | Reserved |
| Unknown | 5 | Cannot assess (schema not synced) |
| Unavailable | 6 | Parse failure |
Scoring rules
Section titled “Scoring rules”| Condition | Level |
|---|---|
SELECT + allow_read_only | Low |
Safe DDL (CREATE TABLE/VIEW/INDEX) + allow_safe_ddl | Low |
| Schema not synced | Unknown |
| Multi-statement DML (>1 DML) | High |
| DROP or TRUNCATE detected | High |
| ≥ 3 review warnings | High |
| CASCADE FK + large table (> max_estimated_rows) | High |
| CASCADE FK + small table | Medium |
| Large table without cascade | Medium |
| 1-2 review warnings | Medium |
| None of the above | Low |
Safe DDL
Section titled “Safe DDL”These CREATE/ALTER statements are considered safe regardless of table size:
CREATE TABLE(new table, no existing data)CREATE VIEWCREATE INDEX CONCURRENTLY(PostgreSQL only)ALTER TABLE ... ADD COLUMN(PostgreSQL only, no lock on existing rows)
Dangerous functions (24)
Section titled “Dangerous functions (24)”Functions that promote a SELECT to ExecuteDml:
dblink, dblink_exec, dblink_connect, lo_export, lo_import, lo_unlink, pg_read_file, pg_read_binary_file, pg_ls_dir, pg_execute_server_program, copy_to, copy_from, set_config, pg_cancel_backend, pg_terminate_backend, pg_sleep, pg_advisory_lock, pg_advisory_xact_lock, pg_notify, sys_exec, sys_eval, load_file, sleep, benchmark
See also
Section titled “See also”- Auto-Approve — how risk scoring drives auto-approve
- Policies Overview — fail-closed principle
- Configuration Reference — full config fields