A connection id can no longer select somebody else's database provider
Reported privately by @NotAFlightRisk as GHSA-3wh2-8x78-jfw4, scored 8.8. Upgrade if more than one account reaches your instance.
getOrCreateProvider keyed its provider cache on connection.id, and that id arrives in the request body: resolveConnection returned an inline connection verbatim, id included. Naming an id another session had open returned that session's live provider, already authenticated as them, with the credentials in the request never compared against it. Seed ids are operator-chosen slugs, so a user account could reach a connection restricted to roles: ["admin"]. Sending a different queryTimeout on the same forged id evicted the victim's provider instead of borrowing it.
The key is now derived rather than supplied. The stored id is framed together with connectionFingerprint, which says which server the connection resolves to, and a digest of its credentials, which says as whom. A forged id buys nothing: reaching an entry costs the victim's server address and secrets, and holding those would allow an honest connection anyway. The id moves onto the cache entry, which is what removeProvider, the idle sweep and connectionStillServed now match on.
resolveConnection also stops honouring a seed: id claimed by an inline connection, so that namespace passes through one role gate rather than two doors.
Both paths were reproduced against the real SQLite driver, and on the agent execution profiles where the profiled cache framed the id the same way, before anything was changed. Those reproductions are the tests that guard it now.
Schema diff reads a column default as SQL, not as a value
A default was emitted by interpolating the value the engine reported, and compared for truthiness rather than for presence. Three consequences, all fixed here: a default of 0, '' or false read as absent and was dropped from the generated DDL; a MariaDB default came back as the expression text where MySQL returns the value, so the same column diffed against itself; and ClickHouse MATERIALIZED, ALIAS and EPHEMERAL columns were emitted with a DEFAULT clause, which no ClickHouse accepts on them, in both ADD COLUMN and CREATE TABLE.
The MySQL and MariaDB reading is pinned against live servers rather than inferred, and the provider stores the flavour it measured instead of the version string it guessed from.
Elasticsearch API key authentication
An Elasticsearch connection takes an API key id and secret as well as a username and password, sent as the Authorization: ApiKey base64(id:secret) scheme Elasticsearch publishes. The key pair wins when both it and a username are configured, since it is the scheme an operator adds on purpose; either half missing falls back rather than sending a half-formed header.
OpenSearch is deliberately unchanged. Nothing has measured whether its security plugin accepts the same scheme, so the form does not offer the fields there rather than guessing an answer.
Query results page from the stats strip
The preview cap used to be written into the SQL text, which meant a starter query carrying its own bound silently lost the offset behind it, and a user-written LIMIT n was indistinguishable from a cap the app applied. The cap now travels as an execution option and leaves the SQL alone: a LIMIT you typed is a hard bound that is never paged past, while a capped preview is readable beyond its first page. The control is the stats strip itself, so no chrome was added below the grid.
Also in this release
- The example compose stacks publish their PostgreSQL and Vault containers on the loopback interface only, so a demo brought up on a host with a public address no longer exposes them.
- The brand mark is adopted across every asset, with the ids in the static SVGs namespaced so two of them on one page no longer collide.
- YunoHost, Civo Kubernetes Marketplace and the 1Panel community app store join the distribution channel inventory.
DOCKERHUB.mdis published to the Docker Hub listing on release, so the page stops trailing the repository.- The Kubero install docs link points at a page that exists, and the CapRover template description fits the 200 character limit the catalog enforces.
- The Japanese, Spanish, Urdu and Hindi READMEs carry the PostgreSQL Clients link the English one has.
Helm chart: 0.1.67
Tracks app release 0.16.2. No packaged template, value or default moves, so the upgrade is the image. artifacthub.io/containsSecurityUpdates is true for this version: the provider cache defect above is a cross-account authorization failure, and an operator running shared or seeded connections should weigh it rather than read a generic tracking line.
helm repo add libredb https://libredb.org/libredb-studio/
helm upgrade --install libredb-studio libredb/libredb-studio --version 0.1.67
Contributors
This release carries work from @NotAFlightRisk, @nawazish2, @chiliec, @KodYazicam, @Lingikaushikreddy, @rahimahisah17, @sloemo01, @t957095, @yusuf-gundogdu, @DevvoLazza, @Dharshini-RS03, R. Martins Nascimento, Mehmet Fatih DAYAN and @cevheri.
Reported by @NotAFlightRisk (GHSA-3wh2-8x78-jfw4), @nktnet1 (#708) and @lucaspereirasouzat (#816).
Full changelog: 0.16.1...0.16.2