From 8b10f58e1b7abc80132757329f82a55caff75047 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Tue, 8 Sep 2026 21:16:35 -0700 Subject: [PATCH] Reject untrusted table-valued PRAGMA reads --- datasette/write_sql.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/datasette/write_sql.py b/datasette/write_sql.py index ca144a72..127ee7db 100644 --- a/datasette/write_sql.py +++ b/datasette/write_sql.py @@ -83,6 +83,22 @@ def decision_for_write_sql_operation( ) if operation.operation == "function": return IgnoreWriteSqlOperation("SQL function") + if ( + operation.operation == "read" + and operation.target_type == "table" + and operation.table is not None + and operation.table_kind is None + and operation.table.lower().startswith("pragma_") + ): + # Eponymous table-valued PRAGMA functions (e.g. pragma_table_info("secret")) + # report a read of the synthetic "pragma_table_info" table, not of the + # table passed as an argument. That means a view-table denial on the real + # table is never consulted, so these could otherwise be used to read + # schema metadata (column names, table lists, ...) for tables the actor + # is not allowed to view. Reject them outright in untrusted write SQL, + # including inside CREATE VIEW bodies (whose reads are discovered here + # via the rolled-back dependency-read analysis above). + return UnsupportedWriteSqlOperation(unsupported_message) if ( operation.operation == "read" and operation.target_type == "table"