CVE-2024-10976 Overview
CVE-2024-10976 is a row-level security (RLS) bypass vulnerability in PostgreSQL that allows reused queries to view or modify rows that were not intended to be accessible under the current user context. This vulnerability stems from incomplete tracking of tables with row security policies, specifically affecting scenarios where subqueries, WITH queries, security invoker views, or SQL-language functions reference tables protected by RLS policies.
This vulnerability is related to previous issues addressed in CVE-2023-2455 and CVE-2016-2193, which attempted to fix interactions between row security and user ID changes. However, those fixes missed certain edge cases that this vulnerability exploits.
Critical Impact
Attackers with low privileges can potentially bypass row-level security policies to read or modify data they should not have access to, undermining database access controls in multi-tenant or role-based architectures.
Affected Products
- PostgreSQL versions before 17.1
- PostgreSQL versions before 16.5
- PostgreSQL versions before 15.9
- PostgreSQL versions before 14.14
- PostgreSQL versions before 13.17
- PostgreSQL versions before 12.21
Discovery Timeline
- November 14, 2024 - CVE-2024-10976 published to NVD
- November 3, 2025 - Last updated in NVD database
Technical Details for CVE-2024-10976
Vulnerability Analysis
This vulnerability affects PostgreSQL databases that utilize row-level security (RLS) policies created via CREATE POLICY. The core issue lies in how PostgreSQL's query planner caches and reuses query plans across different role contexts.
When a query is initially planned under one role and subsequently executed under a different role (such as through SET ROLE operations or within security definer functions), PostgreSQL may incorrectly apply the original role's RLS policies instead of the current role's policies. This occurs because the query planner does not fully track table references in certain SQL constructs, leading to stale policy application.
The vulnerability specifically manifests in:
- Subqueries that reference RLS-protected tables
- Common Table Expressions (WITH queries) accessing secured tables
- Security invoker views that query tables with role-specific policies
- SQL-language functions that reference RLS-protected tables
Root Cause
The root cause is incomplete dependency tracking in PostgreSQL's query plan caching mechanism. When a query plan is generated, PostgreSQL should invalidate cached plans when the security context changes in ways that would affect RLS policy evaluation. The tracking mechanism failed to account for certain nested query structures where table references with RLS policies exist within subqueries, CTEs, security invoker views, or SQL functions.
This represents a case of improper access control (CWE-1250) where the database system fails to properly enforce security boundaries when query execution context changes.
Attack Vector
Exploitation requires an authenticated user with the ability to execute queries against the database. The attacker must:
- Identify an application pattern where query plans are reused across role transitions
- Understand the specific RLS policies in place and which roles they apply to
- Craft queries that exploit the plan reuse mechanism to access data under an incorrect policy context
The attack is network-accessible and requires low privileges, though the attacker must have detailed knowledge of the target application's query patterns and security configuration. An attacker could exploit this through security definer functions that change effective roles, or by manipulating sessions that use SET ROLE commands while reusing prepared statements or cached plans.
Since no verified code examples are available, administrators should review the PostgreSQL Security Advisory for detailed technical information about exploitation scenarios.
Detection Methods for CVE-2024-10976
Indicators of Compromise
- Unexpected data access patterns in audit logs where users access rows outside their normal scope
- Anomalous query execution following SET ROLE commands or security definer function calls
- Users accessing data from tables with RLS policies that should be restricted based on their role
- Prepared statement or cached query plan usage patterns that span role context changes
Detection Strategies
- Enable and review PostgreSQL audit logging (log_statement = 'all') to identify suspicious data access patterns
- Monitor for frequent SET ROLE commands followed by queries against RLS-protected tables
- Implement application-level logging to track user context changes and correlate with database access
- Use query analysis tools to identify queries that reference RLS-protected tables within subqueries, CTEs, or security invoker views
Monitoring Recommendations
- Configure log_connections and log_disconnections to track session lifecycle and role changes
- Implement row-level audit triggers on sensitive tables protected by RLS policies
- Deploy database activity monitoring solutions that can correlate role changes with subsequent query behavior
- Review application code for patterns that reuse prepared statements across role context switches
How to Mitigate CVE-2024-10976
Immediate Actions Required
- Upgrade PostgreSQL to a patched version: 17.1, 16.5, 15.9, 14.14, 13.17, or 12.21
- Audit applications for query plan reuse patterns that span role changes
- Review security definer functions that access RLS-protected tables
- Consider disabling plan caching for sensitive queries using plan_cache_mode = force_custom_plan where applicable
Patch Information
PostgreSQL has released security updates addressing this vulnerability. Administrators should upgrade to the following versions:
- PostgreSQL 17.x: Upgrade to version 17.1 or later
- PostgreSQL 16.x: Upgrade to version 16.5 or later
- PostgreSQL 15.x: Upgrade to version 15.9 or later
- PostgreSQL 14.x: Upgrade to version 14.14 or later
- PostgreSQL 13.x: Upgrade to version 13.17 or later
- PostgreSQL 12.x: Upgrade to version 12.21 or later
Refer to the PostgreSQL Security Advisory for official patch information. Additional advisories are available from Debian LTS and NetApp.
Workarounds
- Avoid using SET ROLE in sessions that also execute queries against RLS-protected tables with cached plans
- Refactor security definer functions to avoid direct references to RLS-protected tables in subqueries or CTEs
- Use DISCARD PLANS after role changes to force query re-planning with the correct security context
- Implement application-level access controls as a defense-in-depth measure alongside RLS
-- Force plan invalidation after role changes
SET ROLE application_user;
DISCARD PLANS; -- Clear cached plans to ensure correct RLS policy application
-- Now execute queries against RLS-protected tables
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


