From a365903d56fa90cc427d17044712c9a714a57c8e Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Tue, 8 Sep 2026 21:16:35 -0700 Subject: [PATCH] Require view permission before returning written rows --- datasette/views/row.py | 9 ++++++++- datasette/views/table.py | 9 +++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/datasette/views/row.py b/datasette/views/row.py index 6501623f..c8179a9e 100644 --- a/datasette/views/row.py +++ b/datasette/views/row.py @@ -838,7 +838,14 @@ class RowUpdateView(BaseView): result = {"ok": True} returned_row = None - if data.get("return"): + # Only read back and disclose the stored row if the actor is also + # allowed to view this table - update-row alone must not be usable + # to read data the actor cannot otherwise see. + if data.get("return") and await self.ds.allowed( + action="view-table", + resource=TableResource(database=resolved.db.name, table=resolved.table), + actor=request.actor, + ): results = await resolved.db.execute( resolved.sql, resolved.params, truncate=True ) diff --git a/datasette/views/table.py b/datasette/views/table.py index f863b8a1..903709d2 100644 --- a/datasette/views/table.py +++ b/datasette/views/table.py @@ -1157,6 +1157,15 @@ class TableInsertView(BaseView): # TODO: narrow to expected write errors so Datasette bugs surface as 500s return Response.error([str(e)]) result = {"ok": True} + # Only read back and disclose stored rows if the actor is also + # allowed to view this table - insert-row/update-row alone must + # not be usable to read data the actor cannot otherwise see. + if should_return and not await self.ds.allowed( + action="view-table", + resource=TableResource(database=database_name, table=table_name), + actor=request.actor, + ): + should_return = False if should_return: if upsert: # Fetch based on initial input IDs