Issue 193: proven on a throwaway server, fixed for postgres by mesh-catalog PR 209; mssql has the same hole

This commit is contained in:
2026-10-02 00:09:38 +02:00
parent b13ef1be81
commit 696957aa5e
@@ -2,7 +2,7 @@
status: located
opened: 2026-10-02
located-in: [mesh-catalog modules/postgres/client.ts (readOnlyQuery)]
fixed-by:
fixed-by: [mesh-catalog PR 209 (postgres; open)]
amended-design:
---
@@ -51,3 +51,30 @@ so that includes anyone logged in on a machine running the console.
instead of the command-line client, so a row is an object keyed by its columns.
- **The check 0159 lacks:** a test that sends a commit followed by a write and asserts the write is
refused and nothing changed. Another asserts a two-column row comes back keyed by both columns.
## Proven, 2026-10-02
On a throwaway server — the same engine image, no network, reached over a socket — the module's code
from the catalogue's main branch ran `COMMIT; COPY (select 1) TO PROGRAM '<a command>'` and **the
command ran on the database host** as the server's own user. `COMMIT; DROP TABLE t` executed the drop
outside the read-only transaction; the wrapper's own trailing rollback happened to undo it, which a
caller ending their statement with a commit of their own would get past (not tried). Nothing was tried
against the live store.
The fix (mesh-catalog PR 209) runs the caller's statement as a login granted `pg_read_all_data` and
nothing else, read-only by its role and its session, with a password the mesh mints as one of the
module's own secrets; without that password the call is refused rather than run as the admin. On the
same throwaway server every escape above, and `SET ROLE`, `RESET SESSION AUTHORIZATION`, turning
read-only off, creating a table, altering the role and reading a server file, is refused; a plain
select comes back keyed by its columns. One attempt — turning the transaction's read-only off, then
deleting — got past the first layer and was stopped by the second, which is why both exist.
**Not answered by the statement-count fix proposed above.** The command-line client sends one string
in one message, so several statements still arrive together. They are harmless as the reader, and
refusing them is left to whoever moves the module to a driver.
## The same hole, elsewhere
The `mssql` module wraps a caller's statement the same way (`BEGIN TRANSACTION; … ROLLBACK;` as its
administrator) for its own `mssql_query` tool. It holds no seat, but the console may call it. It
needs the same change: a login that can only read, and no wrapper as text. Open.