v2.3.0
pREST v2.3.0 β critical _select SQL-injection fix (GHSA-qvx3-q8vx-9q3c), multi-adapter architecture with Postgres/TimescaleDB auto-detect, and JWKS hardening.
Released: July 22, 2026
GitHub tag Β· Compare v2.2.0...v2.3.0
v2.3.0 is a security and architecture release. It fixes an unauthenticated SQL-injection in the _select projection (GHSA-qvx3-q8vx-9q3c, #1002) and lands the multi-adapter architecture β an adapter registry with automatic PostgreSQL / TimescaleDB detection and per-database URL routing (#999).
Docker:
prest/prest:v2.3.0Go install:
go install github.com/prest/prest/v2/cmd/prestd@v2.3.0
Security: upgrade from v2.2.0 (and earlier v2.x) as soon as possible. The _select fix addresses a CVSS 9.8 unauthenticated injection. See Security below.
The versioned Docker tag (prest/prest:v2.3.0) and the GitHub release page are still publishing. In the meantime, prest/prest:latest (and latest-noplugins) carry the v2.3.0 code.
See Changes since v2.2.0 for the commit list.
Highlights
Security: _select SQL-injection fix (#1002)
An unauthenticated SQL-injection in the _select projection was fixed (GHSA-qvx3-q8vx-9q3c, CVSS 9.8) β a follow-up to CVE-2025-58450. Both the field-projection and _count paths now pass through a single validation gate.
Behavior change. _select (and _count) values now accept only:
Wildcard
*
Identifier (optionally dotted)
id, public.users.name
Colon-syntax aggregate
sum:salary, avg:rating
Pre-quoted aggregate
SUM("salary") AS "total"
Aggregates are limited to SUM, AVG, MAX, MIN, STDDEV, VARIANCE. Anything else β subselects, pg_* probing, extra parentheses β returns 400 ErrInvalidIdentifier. _count field names are now quoted in the generated SQL. See Parameters β _select validation.
Multi-adapter architecture (#999)
pREST can now register and serve multiple databases through different adapters in one process:
Adapter registry
Databases map to an adapter by alias
Automatic detection
On connect, pREST tries TimescaleDB first, falls back to PostgreSQL β in single-DB and per-alias multi-DB mode. No new config
URL routing
The {database} path segment selects the adapter for the request
Timescale isolation
_time_bucket / time_bucket and _timescaledb_* schema filtering live in the Timescale adapter; the base Postgres adapter is a no-op
This uses the existing multi-database registry ([[databases]] / DATABASE_ALIAS_N / DATABASE_URL_N) that shipped in v2.2.0 β no new env vars. Guide: Multi-database Β· TimescaleDB.
JWKS / JWT hardening (#1002)
JWKS handling migrated to jwx/v3. JWKS fetch now rejects non-2xx responses, caps the response body at 1 MiB, and redacts the URL (drops userinfo, query, and fragment) in logs. Key-matching semantics are unchanged, and there are no config or environment changes β jwt.jwks / jwt.wellknownurl still work as before. See Auth β JWKS fetch hardening.
Changes since v2.2.0
Fix unauthenticated _select SQL-injection (GHSA-qvx3-q8vx-9q3c); migrate JWKS to jwx/v3 with non-2xx rejection, 1 MiB body cap, and URL redaction
Multi-adapter registry, automatic Postgres/TimescaleDB detection, adapter-selector routing, Timescale feature isolation
Full detail: compare v2.2.0...v2.3.0.
Upgrading from v2.2.0
No configuration changes are required; this is a drop-in update.
Deploy
prest/prest:v2.3.0(orlatestwhile the versioned tag publishes), the matching binary, orgo install β¦@v2.3.0.Review
_selectusage. If clients send non-standard projections (raw SQL functions, quoted expressions outside the aggregate whitelist), they now return400. Move complex projections to custom queries.TimescaleDB aliases are now auto-detected and gain
_time_bucketwithout config changes β see Multi-database.MCP at
/_mcpand Studio at/_studio/are unchanged from v2.2.0.
Related
Last updated