From 628cec8f0cd40ea9eb8b5b14c2b3a19edb6135ab Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Wed, 9 Sep 2026 08:11:20 -0700 Subject: [PATCH] Block framing of stored-query mutation forms --- datasette/views/database.py | 8 +++++++- datasette/views/stored_queries.py | 24 +++++++++++++----------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/datasette/views/database.py b/datasette/views/database.py index 2cb59dc0..da207601 100644 --- a/datasette/views/database.py +++ b/datasette/views/database.py @@ -40,7 +40,11 @@ from datasette.write_sql import QueryWriteRejected from . import Context from .base import DatasetteError, View, stream_csv -from .query_helpers import _ensure_stored_query_execution_permissions, _table_columns +from .query_helpers import ( + _block_framing, + _ensure_stored_query_execution_permissions, + _table_columns, +) from .table_create_alter import _create_table_ui_context from .table_extras import ( QueryExtraContext, @@ -1141,6 +1145,8 @@ class QueryView(View): assert False, f"Invalid format: {format_}" if datasette.cors: add_cors_headers(r.headers) + if stored_query_write and format_ == "html": + _block_framing(r) return r diff --git a/datasette/views/stored_queries.py b/datasette/views/stored_queries.py index 0bbe9f38..03bd9b29 100644 --- a/datasette/views/stored_queries.py +++ b/datasette/views/stored_queries.py @@ -279,7 +279,7 @@ class QueryCreateView(BaseView): ), ) response.status = status - return response + return _block_framing(response) async def get(self, request): db = await self.ds.resolve_database(request) @@ -527,7 +527,7 @@ class QueryEditView(BaseView): ), ) response.status = status - return response + return _block_framing(response) async def get(self, request): db, query_name, existing = await self._load(request) @@ -639,15 +639,17 @@ class QueryDeleteView(BaseView): return Response.error( ["Trusted queries cannot be deleted using the API"], 403 ) - return await self.render( - ["query_delete.html"], - request, - { - "database": db.name, - "database_color": db.color, - "query": stored_query_to_dict(existing), - "query_url": self.ds.urls.table(db.name, query_name), - }, + return _block_framing( + await self.render( + ["query_delete.html"], + request, + { + "database": db.name, + "database_color": db.color, + "query": stored_query_to_dict(existing), + "query_url": self.ds.urls.table(db.name, query_name), + }, + ) ) async def post(self, request):