Subject: Avoid leaking system path from pg_available_extensions

From: Chao Li <[email-masked]>
Date: Wed, 20 May 2026 09:00:29 +0800

Hi,

I just tested “Add paths of extensions to pg_available_extensions”, and found an issue.

This is a simple repro:
```
evantest=# reset extension_control_path;
RESET
evantest=# select * from pg_available_extensions where name = 'plpgsql';
  name   | default_version | installed_version | location |           comment
---------+-----------------+-------------------+----------+------------------------------
 plpgsql | 1.0             | 1.0               | $system  | PL/pgSQL procedural language
(1 row)

evantest=# set extension_control_path='';
SET
evantest=# select * from pg_available_extensions where name = 'plpgsql';
  name   | default_version | installed_version |             location             |           comment
---------+-----------------+-------------------+----------------------------------+------------------------------
 plpgsql | 1.0             | 1.0               | /usr/local/pgsql/share/extension | PL/pgSQL procedural language
(1 row)
```

When extension_control_path is not set, location shows “$system", which is consistent with what the documentation says:
```
       <para>
        The default value for this parameter is
        <literal>'$system'</literal>. If the value is set to an empty
        string, the default <literal>'$system'</literal> is also assumed.
       </para>
```

However, as shown above, when I set extension_control_path to an empty string, the absolute system path is displayed. I consider this an information leakage bug.

The fix is straightforward; see the attached patch for details. After the fix, when extension_control_path is an empty string, location shows “$system” now:
```
evantest=# set extension_control_path='';
SET
evantest=# select * from pg_available_extensions where name = 'plpgsql';
  name   | default_version | installed_version | location |           comment
---------+-----------------+-------------------+----------+------------------------------
 plpgsql | 1.0             | 1.0               | $system  | PL/pgSQL procedural language
(1 row)
```

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/

---

From: Chao Li <[email-masked]>
Date: Wed, 20 May 2026 09:07:49 +0800

> On May 20, 2026, at 09:00, Chao Li <[email-masked]> wrote:
> 
> Hi,
> 

Oops, forgot the attachment. Here comes it.

Best regards,

---

From: lu feng <[email-masked]>
Date: Thu, 21 May 2026 16:55:47 +0800

Chao Li <[email-masked]> 于2026年5月20日周三 09:08写道：

> > plpgsql | 1.0             | 1.0               |
> /usr/local/pgsql/share/extension | PL/pgSQL procedural language
> > (1 row)
> > ```
> >
> > When extension_control_path is not set, location shows “$system", which
> is consistent with what the documentation says:
> > ```
> >       <para>
> > However, as shown above, when I set extension_control_path to an empty
> string, the absolute system path is displayed. I consider this an
> information leakage bug.
> >
> > The fix is straightforward; see the attached patch for details. After
> the fix, when extension_control_path is an empty string, location shows
> “$system” now:
> > ```
> Thanks for the patch. I just reproduced the problem and verified the fix.
So this patch looks good to me.

Regards,
Lu Feng

---

From: Matheus Alcantara <[email-masked]>
Date: Thu, 21 May 2026 12:12:56 -0300

>    name   | default_version | installed_version | location |           comment

Hi, thank you for sharing the bug with the fix.

I've reproduced the issue and the fix looks correct to me.

--
Matheus Alcantara
EDB: https://www.enterprisedb.com

---

From: Jim Jones <[email-masked]>
Date: Fri, 22 May 2026 09:25:54 +0200

> I've reproduced the issue and the fix looks correct to me.

same here, +1

I was wondering if creating a constant for it would be, stylistically
speaking, a cleaner solution. For instance:

#define EXTENSION_SYSTEM_MACRO  "$system"

I realize that it's used only inside get_extension_control_directories()
but since it is even mentioned in the docs, I guess it wouldn't be a bad
idea.

Thanks!

Best, Jim

---

From: Matheus Alcantara <[email-masked]>
Date: Fri, 22 May 2026 12:40:28 -0300

>> I've reproduced the issue and the fix looks correct to me.

Thank you for also testing.

> but since it is even mentioned in the docs, I guess it wouldn't be a bad

I'm not against it but I don't think that it's necessary since as you 
mention, only get_extension_control_directories() use.

---

From: Chao Li <[email-masked]>
Date: Tue, 26 May 2026 15:14:25 +0800

> On May 22, 2026, at 23:40, Matheus Alcantara <[email-masked]> wrote:
> 
> I'm not against it but I don't think that it's necessary since as you mention, only get_extension_control_directories() use.
> 
> --
> Matheus Alcantara

In theory, I’m not against the idea either. In practice, there are many hard-coded strings in the source tree, and I’m not sure where the right place would be to define this macro.

Since this string is only used in get_extension_control_directories(), and now it is used three times, I defined it at the beginning of the function and undefined it at the end. Let’s see if there are any objections to that.

Please see the attached v2.
Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/

---

From: Jim Jones <[email-masked]>
Date: Tue, 26 May 2026 12:02:45 +0200

> Since this string is only used in get_extension_control_directories(), and now it is used three times, I defined it at the beginning of the function and undefined it at the end. Let’s see if there…

I don't feel strongly about it. I only brought it up because hardcoded
strings used in multiple places are usually a recipe for oversights and
painful debugging down the road. That said, as I mentioned, I understand
the argument that this is scoped to a single function, and the fact
they're pretty close to one another also makes it less likely to be
missed, but there is no guarantee it'll stay like that forever.

Thanks for the fix!

Best, Jim

---

From: Matheus Alcantara <[email-masked]>
Date: Tue, 26 May 2026 10:29:58 -0300

> Please see the attached v2.

We have such pattern in other parts of the codebase (e.g 
pg_resetwal.c), so it works for me.

Thanks for the patch.

---

From: Andrew Dunstan <[email-masked]>
Date: Sat, 30 May 2026 09:21:21 -0400

On 2026-05-26 Tu 9:29 AM, Matheus Alcantara wrote:
>>> I'm not against it but I don't think that it's necessary since as 
>>> you mention, only get_extension_control_directories() use.
>>>
>>
>> In theory, I’m not against the idea either. In practice, there are 
>> many hard-coded strings in the source tree, and I’m not sure where 
>> the right place would be to define this macro.
>>
>> Since this string is only used in 
>> get_extension_control_directories(), and now it is used three times, 
>> I defined it at the beginning of the function and undefined it at the 
>> end. Let’s see if there are any objections to that.
>>

Pushed.

cheers

andrew

--
Andrew Dunstan

---

From: Chao Li <[email-masked]>
Date: Sun, 31 May 2026 12:26:51 +0800

> On May 30, 2026, at 21:21, Andrew Dunstan <[email-masked]> wrote:
> 
> 
>> We have such pattern in other parts of the codebase (e.g pg_resetwal.c), so it works for me.
>> 
>> Thanks for the patch.
>> 
>> 
> 
> Pushed.
> 
> 
> cheers
> 
> 
> andrew
> 
> --
> Andrew Dunstan

Thanks for pushing.

Best regards,