Deny user-authored schema table reads in write SQL

Stop marking sqlite_master and sqlite_schema reads as internal as soon as the SQLite authorizer reports them. The later DDL-aware pass still treats schema catalog access as internal when it accompanies semantic CREATE, ALTER, or DROP operations.

This makes explicit catalog reads in write SQL fall through to the deny-by-default path as unsupported read schema operations, preventing queries from copying private table definitions into writable tables.

Refs https://github.com/simonw/datasette/pull/2749#issuecomment-4559073803
This commit is contained in:
Simon Willison 2026-05-27 16:14:50 -07:00
commit 1932f8429f
4 changed files with 84 additions and 14 deletions

View file

@ -65,6 +65,26 @@ def test_analyze_uses_sqlite_schema_as_default_database(conn):
}
def test_analyze_user_schema_table_read_is_not_internal(conn):
analysis = analyze_sql_tables(
conn,
"insert into log select sql from sqlite_master where name = 'dogs'",
database_name="data",
)
assert {
"operation": "read",
"target_type": "schema",
"database": "data",
"sqlite_schema": "main",
"table": None,
"target": "sqlite_master",
"columns": ("name", "sql"),
"source": None,
"internal": False,
} in [operation_dict(operation) for operation in analysis.operations]
def operation_dict(operation):
return {
"operation": operation.operation,