May 9, 2019·5 min read·engineeringpostgresqlsecurityplanner

PostgreSQL 11.3 closes a row security leak in planner statistics

PostgreSQL 11.3 prevents selectivity estimators from exposing sampled values hidden by row security. The release also fixes partition-routing disclosure and Windows installer permissions.

Row security can hide a table row while a copy of one of its values remains available to the query planner. PostgreSQL 11.3 closes a disclosure path through that second representation. A user-defined operator could inspect sampled column values during selectivity estimation, including values taken from rows that the caller could not read.

The May 9 announcement identifies this issue as CVE-2019-10130. It accompanies another server security fix and two Windows installer fixes. The release's most instructive change concerns the relationship between query optimization and access control, since a permission rule has to apply wherever protected data becomes available.

I appreciate PostgreSQL's planner diagnostics because understanding a chosen plan is essential to tuning it. This bug illustrates the corresponding security obligation. Information used to choose a plan can contain real data, so permission enforcement cannot begin only when the executor reads table rows.

A sample can reveal a protected value

The 11.3 release notes describe selectivity estimators applying user-defined operators to values in pg_statistic, including most-common values. Estimation uses those values to help assess how a condition might behave. Applying an operator to a value also gives that operator an opportunity to observe it.

Earlier restrictions introduced for CVE-2017-7484 considered whether the caller could read the column. The new issue is that column permission and row visibility answer different questions. A user can hold SQL permission to read a column while a row-level security policy prevents that user from reading certain rows.

If the sample includes a value from one of those excluded rows, column-level permission alone is insufficient. A leaky operator can expose information from the sample even though ordinary row retrieval would enforce the policy. The disclosure path passes through planning, before the protected row would become an executor result.

Version 11.3 tightens the rule for using non-leakproof operators on statistics data. Such operators can use the data only when there is no relevant row-level security policy. That change addresses the mismatch between the table's access rules and the planner's permission to expose representative values.

The affected branches named in the announcement are 9.5, 9.6, 10 and 11. The maintenance versions released alongside 11.3 include 10.8, 9.6.13 and 9.5.17. This is relevant to existing row-security deployments across those branches, independently of whether they use the newer partitioning facilities.

A useful implication follows without assuming an exploit in any particular application. Moving a value into an internal summary does not remove its security meaning. When extensible code can operate on that summary, the database has to consider which original values that code is entitled to see.

Views complicate whose permissions apply

The release also repairs the identity used for some related permission decisions. When a query accesses an underlying table through a view, the planner must use the appropriate user's privileges when deciding whether a leaky operator may see statistics. The notes explain that this should use the view owner's privileges in the described case.

That aligns the planner's visibility rules with the executor's. The recorded consequence of the earlier mismatch includes unnecessarily poor plans. Security-sensitive checks can be incorrect by denying information that should be available, as well as by exposing information that should remain hidden.

A separate fix concerns subqueries inside row-security policy expressions. When the protected table is accessed through a view, those subqueries must execute with the correct user's permissions. The notes identify the mistaken behavior as sometimes using the view caller's permissions where the view owner's permissions should apply.

These details make the security model more concrete. It is insufficient to say that a query has one user and all of its internal work uses that identity. Views and policy expressions introduce permission contexts that different parts of the query implementation must preserve consistently.

My preference for database-enforced rules depends on that consistency. An application can benefit from central row policies, but those policies need to remain meaningful through planning and view expansion. The release repairs both the availability of sampled values and the user identity used in related decisions.

Partition routing has a separate disclosure bug

CVE-2019-10129 concerns PostgreSQL 11's partition routing. The release notes identify access to already-freed memory while reporting a routing error. That can crash the server, and the notes describe the possibility of disclosing server memory contents.

This is different from the statistics issue. The planner leak involves a value that remains intentionally stored for estimation but is visible to the wrong operation. The partition-routing problem involves a memory lifetime error in a diagnostic path. Both can expose information, but their mechanisms and affected scope differ.

The distinction matters when assessing the release. The announcement describes a purpose-crafted insert into a partitioned table for the routing issue. Row-security use is not the stated prerequisite for that bug. Operators should not infer that avoiding row policies removes the relevance of the other server security fix.

Partitioning also receives non-security correctness repairs. These include catalog corruption during certain ALTER TABLE operations, tuple routing with dropped attributes in multi-level partitioning, and behavior when every table can be excluded from an update or delete. The release covers several points where partition structure interacts with ordinary SQL operations.

Installer permissions affect the service account

The two remaining CVEs concern permissive Windows directory access. CVE-2019-10127 applies to the BigSQL installer, and CVE-2019-10128 applies to the EnterpriseDB installer. The announcement says the binary and data directories were not sufficiently restricted, allowing unprivileged accounts to cause code execution as the PostgreSQL service account.

The updated installers correct permissions for new and existing installations. The project also advises users of other Windows installation methods to check that binary directories are writable only by trusted users and data directories are accessible only to trusted users. These are installation properties, so they should not be mistaken for the server's SQL-level permission checks.

The maintenance update does not require dumping and reloading an existing 11.x database. The project recommends prompt upgrades for affected Windows installer users and for users of the branches affected by the server issues. Its security fixes address distinct locations where privileged data or execution authority becomes available, including the planner's statistical sample and the files used by the service account.