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:
+28
-1
@@ -2,7 +2,7 @@
|
|||||||
status: located
|
status: located
|
||||||
opened: 2026-10-02
|
opened: 2026-10-02
|
||||||
located-in: [mesh-catalog modules/postgres/client.ts (readOnlyQuery)]
|
located-in: [mesh-catalog modules/postgres/client.ts (readOnlyQuery)]
|
||||||
fixed-by:
|
fixed-by: [mesh-catalog PR 209 (postgres; open)]
|
||||||
amended-design:
|
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.
|
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
|
- **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.
|
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.
|
||||||
|
|||||||
Reference in New Issue
Block a user