Avoid leaking system path from pg_available_extensions

First seen: 2026-05-20 01:00:29+00:00 · Messages: 2 · Participants: 1

Latest Update

2026-05-20 · claude-opus-4-6

Technical Analysis: Avoiding System Path Leakage from pg_available_extensions

Core Problem

The thread identifies an information disclosure vulnerability in the recently added location column of the pg_available_extensions system view, introduced by the "Add paths of extensions to pg_available_extensions" feature.

The Bug

The extension_control_path GUC controls where PostgreSQL searches for extension control files. Its documentation states that when set to an empty string, the system should behave as if the default value '$system' is assumed. However, there's an inconsistency in how the pg_available_extensions view reports the location:

Why This Matters Architecturally

  1. Information Leakage: Exposing absolute filesystem paths to SQL-level users reveals server installation details (directory structure, OS layout, custom installation prefixes). This is a security concern, particularly in shared hosting or multi-tenant environments where unprivileged database users should not learn server-side filesystem details.

  2. Violation of Abstraction Contract: The $system token exists precisely to abstract away the physical location of the system extension directory. The documentation explicitly states that an empty string should be equivalent to '$system', so the view output should be consistent regardless of which equivalent representation the user sets.

  3. Inconsistency Between GUC Interpretation and View Output: The GUC parsing layer correctly treats '' as equivalent to '$system' for the purpose of finding extensions, but the view rendering code path apparently resolves the path before checking whether it should be displayed as the symbolic $system token.

Root Cause Analysis

The likely root cause is in the code that generates the location column for pg_available_extensions. When extension_control_path is explicitly set (even to empty string), the code path that resolves the search path apparently expands $system to its physical directory before populating the view column. When the GUC is at its default (NULL/unset) value, a different code path correctly outputs the symbolic $system string.

The distinction is likely between:

Proposed Fix

The patch (mentioned but attached in the follow-up email) is described as "straightforward" — it ensures that when extension_control_path resolves to the system extension directory (whether via explicit '$system' token, empty string, or default), the location column consistently displays $system rather than the resolved absolute path.

The fix likely adds a check in the view-generating function that compares the resolved path against the known system extension directory and substitutes $system if they match, ensuring the abstraction is maintained regardless of how the GUC is configured.

Security Implications

While this is not a critical vulnerability (users with SET privileges already have some level of trust), it violates the principle of least information disclosure. The $system abstraction was deliberately designed to hide server internals, and any code path that bypasses it undermines that design intent. This is particularly relevant for:

Assessment

This is a clean, well-identified edge-case bug in a new feature. The fix is low-risk and narrowly scoped. It should be applied before the feature ships in a release to avoid establishing a behavior that would later require a compatibility-breaking change.