v2.4.1
pREST v2.4.1 β the MCP endpoint now honours [expose], closing a catalog discovery bypass, plus a SQL-keyword screen on custom query script values.
Released: July 28, 2026
GitHub tag Β· Compare v2.4.0...v2.4.1
v2.4.1 is a security release with a single commit (#1016). It makes the MCP endpoint honour the [expose] settings β previously /_mcp could enumerate the full catalog even when the REST listing routes were denied β and adds a SQL-keyword screen to values that custom query scripts interpolate into SQL.
Docker:
prest/prest:v2.4.1Go install:
go install github.com/prest/prest/v2/cmd/prestd@v2.4.1
The script-value screen shipped here was too broad and was relaxed in v2.4.2 (#1030). On v2.4.1, a single-word value containing a SQL keyword β sao-joao-do-sul splits into a token do β is silently blanked, and the request still returns 200 with the wrong rows. Go straight to v2.4.2 rather than stopping on v2.4.1.
No configuration keys were added or renamed, and no defaults changed.
Highlights
MCP honours [expose] (#1016)
/_mcp was never routed through the exposure middleware, so an operator who disabled the /databases, /schemas, or /tables REST routes was still serving the entire catalog to any MCP client. The MCP handler now checks the same settings before answering.
When a listing is denied, the corresponding tool returns HTTP 400 with a JSON-RPC error:
{"jsonrpc":"2.0","id":1,"error":{"code":400,"message":"unauthorized listing"}}The REST routes keep returning 401 with {"error": "unauthorized listing"} β same message, different status, because the two surfaces report errors differently.
Discovery (GET /_mcp, tools/list) is pruned rather than blocked:
prest.list_databases
Not advertised; tools/call returns 400
prest.list_schemas
Not advertised; tools/call returns 400
prest.list_tables
Not advertised; tools/call returns 400
prest.select.{database}.{schema}.{table}
Not enumerated at all if any listing is denied
prest.describe_table, prest.select_table
Always advertised
The per-table tools are withheld because their names embed database, schema, and table names and their descriptions embed column names β enumerating them made GET /_mcp a full catalog dump with no tools/call required.
[expose] governs discovery; [access] governs reads. A client that already knows a table name can still read it through prest.select_table subject to permissions. See MCP over HTTP β Tools reference and Configuring pREST β Expose Data.
Clarified [expose] semantics
The three listing flags only take effect while enabled = true. The check is "allowed unless exposure control is on and this listing is off", so hiding a listing takes both keys:
This also means a deployment on the default enabled = false is unaffected by this release.
SQL-keyword screen on script values (#1016)
Values that a /_QUERIES script template interpolates become part of the SQL text. The pre-existing character allow-list was not enough: 0 UNION SELECT passwd FROM pg_shadow needs no quote, comma, or parenthesis, so it passed through into an unquoted comparison such as WHERE 1 = {{.field1}}.
Values are now also rejected when they contain --, ::, or a SQL keyword token (58 keywords, matched case-insensitively, with leading digits stripped so 0union is caught as union).
On v2.4.1 this screen runs on every value and on every inbound header, and a blanked value does not fail the request β the script runs with an empty string substituted and returns 200. Legitimate values are affected: ?status=null, ?sort=order, ?type=table, and any slug containing do, as, or or. v2.4.2 restricts the screen to values containing a space and fails the request instead of silently substituting.
Changes since v2.4.0
MCP endpoint honours [expose]; listing tools refused and per-table tools withheld when exposure control is active; SQL-keyword screen on custom query script values
Full detail: compare v2.4.0...v2.4.1.
Upgrading from v2.4.0
Upgrade to v2.4.2 instead β it contains this release plus the fix for the over-broad script screen. If you do deploy v2.4.1:
Deploy
prest/prest:v2.4.1, the matching binary, orgo install β¦@v2.4.1.On the default
[expose] enabled = false, nothing changes. MCP behaviour only shifts for deployments that actively restrict listings.If you restrict listings, MCP clients relying on auto-discovered
prest.select.{database}.{schema}.{table}tools must switch to the genericprest.select_tabletool.Audit custom query scripts. Any script parameter or header whose value contains a SQL keyword,
--, or::is silently blanked. Rewrite templates to bind values instead of interpolating them β see Custom Queries.
Related
Last updated