> For the complete documentation index, see [llms.txt](https://docs.prestd.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.prestd.com/releases/v2.3.0.md).

# v2.3.0

Released: July 22, 2026

[GitHub tag](https://github.com/prest/prest/releases/tag/v2.3.0) · [Compare v2.2.0...v2.3.0](https://github.com/prest/prest/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](https://github.com/prest/prest/security/advisories/GHSA-qvx3-q8vx-9q3c), [#1002](https://github.com/prest/prest/pull/1002)) and lands the multi-adapter architecture — an adapter registry with automatic PostgreSQL / TimescaleDB detection and per-database URL routing ([#999](https://github.com/prest/prest/pull/999)).

* **Docker:** `prest/prest:v2.3.0`
* **Go install:** `go install github.com/prest/prest/v2/cmd/prestd@v2.3.0`

{% hint style="warning" %}
**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](#security-_select-sql-injection-fix-1002) below.
{% endhint %}

{% hint style="info" %}
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.
{% endhint %}

See [Changes since v2.2.0](#changes-since-v220) for the commit list.

***

## Highlights

### Security: `_select` SQL-injection fix ([#1002](https://github.com/prest/prest/pull/1002))

An unauthenticated SQL-injection in the `_select` projection was fixed ([GHSA-qvx3-q8vx-9q3c](https://github.com/prest/prest/security/advisories/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:

| Form                           | Example                    |
| ------------------------------ | -------------------------- |
| 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](/api-reference/parameters.md#_select-field-validation-v230).

### Multi-adapter architecture ([#999](https://github.com/prest/prest/pull/999))

pREST can now register and serve **multiple databases through different adapters** in one process:

| Capability          | Detail                                                                                                                                   |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| 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](/releases/v2.2.0.md) — no new env vars. Guide: [Multi-database](/get-started/multi-database.md) · [TimescaleDB](/databases/timescaledb.md).

### JWKS / JWT hardening ([#1002](https://github.com/prest/prest/pull/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](/api-reference/auth.md#jwks-fetch-hardening-v230).

***

## Changes since v2.2.0

| PR                                                | Summary                                                                                                                                                                                                                         |
| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [#1002](https://github.com/prest/prest/pull/1002) | Fix unauthenticated `_select` SQL-injection ([GHSA-qvx3-q8vx-9q3c](https://github.com/prest/prest/security/advisories/GHSA-qvx3-q8vx-9q3c)); migrate JWKS to `jwx/v3` with non-2xx rejection, 1 MiB body cap, and URL redaction |
| [#999](https://github.com/prest/prest/pull/999)   | Multi-adapter registry, automatic Postgres/TimescaleDB detection, adapter-selector routing, Timescale feature isolation                                                                                                         |

Full detail: [compare v2.2.0...v2.3.0](https://github.com/prest/prest/compare/v2.2.0...v2.3.0).

***

## Upgrading from v2.2.0

No configuration changes are required; this is a drop-in update.

1. Deploy `prest/prest:v2.3.0` (or `latest` while the versioned tag publishes), the matching binary, or `go install …@v2.3.0`.
2. **Review `_select` usage.** If clients send non-standard projections (raw SQL functions, quoted expressions outside the aggregate whitelist), they now return `400`. Move complex projections to [custom queries](/api-reference/custom-queries.md).
3. TimescaleDB aliases are now **auto-detected** and gain `_time_bucket` without config changes — see [Multi-database](/get-started/multi-database.md#timescale-operators-v230).
4. MCP at `/_mcp` and Studio at `/_studio/` are unchanged from v2.2.0.

***

## Related

* [Parameters — `_select` validation](/api-reference/parameters.md#_select-field-validation-v230)
* [Auth — JWKS fetch hardening](/api-reference/auth.md#jwks-fetch-hardening-v230)
* [Multi-database](/get-started/multi-database.md)
* [TimescaleDB](/databases/timescaledb.md)
* [Configuring pREST](/get-started/configuring-prest.md)
* [v2.2.0 release notes](/releases/v2.2.0.md)
* [Acronyms](/readme/acronyms.md) · [MCP](/readme/acronyms.md#mcp) · [REST](/readme/acronyms.md#rest)
