August 14, 2025·4 min read·engineeringpostgresqlsecurityquery-planning

PostgreSQL 17.6 checks view permissions before planning can expose statistics

CVE-2025-8713 closes gaps in access checks around sampled planner data. The August release also fixes two separate restore-time injection vulnerabilities.

A query can disclose information before it returns a row. PostgreSQL's planner consults sampled column data to estimate what a query will do, and an operator's estimation logic can encounter those samples. CVE-2025-8713 closes permission-checking gaps that let a crafted operator reach statistics belonging to data the caller was not supposed to read.

The August 14 announcement releases PostgreSQL 17.6, 16.10, 15.14, 14.19 and 13.22. It also publishes PostgreSQL 18 Beta 3. The supported-branch updates address three security vulnerabilities, including two distinct problems in dump and restore workflows. The statistics issue concerns confidentiality during planning itself.

I value PostgreSQL's planner visibility because estimates make performance decisions inspectable. This vulnerability shows why the information behind an estimate needs the same care as ordinary query data. Calling it metadata does not make sampled values nonsensitive.

Statistics contain values drawn from tables

The pg_statistic catalog reference says its entries store statistical information about table contents. Access is restricted because the statistics can reveal sensitive information. The readable pg_stats view exposes information only for tables the user can read.

Histograms and most-common-value lists are particularly relevant to this advisory. They contain information about actual column values, rather than only a count of rows. A confidentiality boundary around a table would be incomplete if its sampled values remained available through another path.

This is the mechanism that makes planning a security concern. An estimation operation may have no intention of executing the caller's final query, yet it can still process data drawn from protected rows. Preventing the final result from reaching the caller does not necessarily prevent an earlier computation from observing that data.

Two access-control gaps remained

The CVE-2025-8713 advisory identifies a view-permission case and a row-security case in partitioning or inheritance hierarchies. It says crafted leaky operators could reach histograms and most-common-value lists. Earlier fixes associated with CVE-2017-7484 and CVE-2019-10130 had attempted to close this class of problem, but these gaps remained.

The historical identifiers therefore describe previous work on the same class of vulnerability. They are not the other two new vulnerabilities fixed by this release. The August announcement names CVE-2025-8714 and CVE-2025-8715 separately for its dump-related fixes.

The 17.6 release notes explain the view case. In that case, the view owner could read the underlying table, which satisfied an existing security check. The caller lacked permission on the view, but the planner could apply the leaky function to underlying statistics before checking that permission. PostgreSQL now checks view permissions at the beginning of planning.

That changes when an error can occur. A caller without permission may receive a failure earlier than before. The important property is the ordering of the check relative to the sensitive computation, rather than whether the operation eventually produces a permission-denied result.

A view has more than one relevant identity

The CREATE VIEW documentation distinguishes permissions on the view from permissions on its underlying relations. By default, the view owner's privileges govern access to those relations. A security-invoker view instead uses the invoking user's privileges for underlying access.

This separation is useful for delegated access. A role can receive permission to use a view without receiving general permission to read its source tables. It also means that the database must keep track of which identity authorizes which part of the operation.

The repaired path had allowed one identity's permission to satisfy a check before validating the other identity's access. The view owner being allowed to read the table did not imply that the caller was allowed to use the view. Moving the latter check earlier prevents the planner from processing protected samples for that unauthorized request. This is more specific than adding another check before rows leave the executor. The decision has to precede the estimation function, because the unauthorized observation can already have occurred by the time execution would begin.

Row security also constrains planning inputs

The row-security documentation describes policies that restrict rows available to normal queries and data modifications. Policy expressions normally run before user-supplied conditions, with an exception for functions marked leakproof. Superusers and roles with BYPASSRLS bypass the policy system, and table owners normally do too.

Those documented exceptions matter when assessing a test. A query run as a privileged owner does not demonstrate what an ordinary restricted role can observe. The August advisory's partition and inheritance case concerns samples from rows that policy intended to hide from that caller.

I find this a useful reason to distinguish returned rows from observable information. A row-security policy can define the intended result while another planning operation still needs a separate authorization check. The fix belongs in the database's estimation code because that is where the sampled data becomes available.

Restore tooling crosses a separate authority boundary

CVE-2025-8714 concerns a malicious source-server superuser causing dump output to execute client-side commands when restored through psql. The operating-system account running the restore has authority distinct from the target database role. Trusting a source for database restoration does not automatically authorize it to run shell commands on the restoring machine.

CVE-2025-8715 describes crafted object names containing newlines. They could inject commands into a restore script, with consequences for both the client account and the target database. These findings explain why the August update includes utilities as well as server permission checks.

The statistics fix prevents an unauthorized planning computation before it observes protected samples. The restore fixes address instructions entering a different interpreter through generated output. Both require identifying the authority at the moment data is processed. For installations applying 17.6, the release notes also advise reindexing BRIN indexes using numeric_minmax_multi_ops to repair possible bloat and inefficiency, a separate maintenance action after the code update.