public inbox for pgsql-hackers@postgresql.org
help / color / mirror / Atom feedAvoid leaking system path from pg_available_extensions
6+ messages / 4 participants
[nested] [flat]
* Avoid leaking system path from pg_available_extensions
@ 2026-05-20 01:00 Chao Li <li.evan.chao@gmail.com>
2026-05-20 01:07 ` Re: Avoid leaking system path from pg_available_extensions Chao Li <li.evan.chao@gmail.com>
2026-05-21 15:12 ` Re: Avoid leaking system path from pg_available_extensions Matheus Alcantara <matheusssilv97@gmail.com>
0 siblings, 2 replies; 6+ messages in thread
From: Chao Li @ 2026-05-20 01:00 UTC (permalink / raw)
To: pgsql-hackers; +Cc: Andrew Dunstan <andrew@dunslane.net>; Matheus Alcantara <matheusssilv97@gmail.com>
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/
^ permalink raw reply [nested|flat] 6+ messages in thread
* Re: Avoid leaking system path from pg_available_extensions
2026-05-20 01:00 Avoid leaking system path from pg_available_extensions Chao Li <li.evan.chao@gmail.com>
@ 2026-05-20 01:07 ` Chao Li <li.evan.chao@gmail.com>
2026-05-21 08:55 ` Re: Avoid leaking system path from pg_available_extensions lu feng <fnlo1995@gmail.com>
1 sibling, 1 reply; 6+ messages in thread
From: Chao Li @ 2026-05-20 01:07 UTC (permalink / raw)
To: pgsql-hackers; +Cc: Andrew Dunstan <andrew@dunslane.net>; Matheus Alcantara <matheusssilv97@gmail.com>
> On May 20, 2026, at 09:00, Chao Li <li.evan.chao@gmail.com> wrote:
>
> 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/
>
>
>
>
Oops, forgot the attachment. Here comes it.
Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/
Attachments:
[application/octet-stream] v1-0001-Avoid-leaking-system-path-from-pg_available_exten.patch (2.6K, 2-v1-0001-Avoid-leaking-system-path-from-pg_available_exten.patch)
download | inline diff:
From 0f9398b34a5484edbb93cb7771d6204bb37b6f7c Mon Sep 17 00:00:00 2001
From: "Chao Li (Evan)" <lic@highgo.com>
Date: Wed, 20 May 2026 08:49:15 +0800
Subject: [PATCH v1] Avoid leaking system path from pg_available_extensions
The documentation says that when extension_control_path is set to an
empty string, the default '$system' path is still assumed. However,
get_extension_control_directories() added the system extension directory
with a NULL macro in that case. As a result, pg_available_extensions
could expose the expanded system directory path instead of reporting
'$system' as the location.
Record the implicitly-added system directory with the '$system' macro, so
pg_available_extensions reports the documented symbolic location and does
not leak the actual system path.
Update the extension_control_path TAP test to check the reported location
directly.
Author: Chao Li <lic@highgo.com>
Reviewed-by:
Discussion: https://postgr.es/m/
---
src/backend/commands/extension.c | 2 +-
.../modules/test_extensions/t/001_extension_control_path.pl | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index a330b5fd6ce..98f9d7018ae 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -526,7 +526,7 @@ get_extension_control_directories(void)
{
ExtensionLocation *location = palloc_object(ExtensionLocation);
- location->macro = NULL;
+ location->macro = pstrdup("$system");
location->loc = system_dir;
paths = lappend(paths, location);
}
diff --git a/src/test/modules/test_extensions/t/001_extension_control_path.pl b/src/test/modules/test_extensions/t/001_extension_control_path.pl
index c1cec0dc622..4a013a7da4b 100644
--- a/src/test/modules/test_extensions/t/001_extension_control_path.pl
+++ b/src/test/modules/test_extensions/t/001_extension_control_path.pl
@@ -109,10 +109,10 @@ is($ret, "t",
"\$system extension is shown correctly in pg_available_extensions");
$ret = $node->safe_psql('postgres',
- "set extension_control_path = ''; select count(*) > 0 as ok from pg_available_extensions where name = 'plpgsql'"
+ "set extension_control_path = ''; select location from pg_available_extensions where name = 'plpgsql'"
);
-is($ret, "t",
- "\$system extension is shown correctly in pg_available_extensions with empty extension_control_path"
+is($ret, "\$system",
+ "\$system location is shown correctly in pg_available_extensions with empty extension_control_path"
);
# Test with an extension that does not exists
--
2.50.1 (Apple Git-155)
^ permalink raw reply [nested|flat] 6+ messages in thread
* Re: Avoid leaking system path from pg_available_extensions
2026-05-20 01:00 Avoid leaking system path from pg_available_extensions Chao Li <li.evan.chao@gmail.com>
2026-05-20 01:07 ` Re: Avoid leaking system path from pg_available_extensions Chao Li <li.evan.chao@gmail.com>
@ 2026-05-21 08:55 ` lu feng <fnlo1995@gmail.com>
0 siblings, 0 replies; 6+ messages in thread
From: lu feng @ 2026-05-21 08:55 UTC (permalink / raw)
To: Chao Li <li.evan.chao@gmail.com>; +Cc: pgsql-hackers; Andrew Dunstan <andrew@dunslane.net>; Matheus Alcantara <matheusssilv97@gmail.com>
Chao Li <li.evan.chao@gmail.com> 于2026年5月20日周三 09:08写道:
>
>
> > On May 20, 2026, at 09:00, Chao Li <li.evan.chao@gmail.com> wrote:
> >
> > 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/
> >
> >
> >
> >
>
> Oops, forgot the attachment. Here comes it.
>
> Best regards,
> --
> Chao Li (Evan)
> HighGo Software Co., Ltd.
> https://www.highgo.com/
>
>
>
>
> Thanks for the patch. I just reproduced the problem and verified the fix.
So this patch looks good to me.
Regards,
Lu Feng
^ permalink raw reply [nested|flat] 6+ messages in thread
* Re: Avoid leaking system path from pg_available_extensions
2026-05-20 01:00 Avoid leaking system path from pg_available_extensions Chao Li <li.evan.chao@gmail.com>
@ 2026-05-21 15:12 ` Matheus Alcantara <matheusssilv97@gmail.com>
2026-05-22 07:25 ` Re: Avoid leaking system path from pg_available_extensions Jim Jones <jim.jones@uni-muenster.de>
1 sibling, 1 reply; 6+ messages in thread
From: Matheus Alcantara @ 2026-05-21 15:12 UTC (permalink / raw)
To: Chao Li <li.evan.chao@gmail.com>; pgsql-hackers; +Cc: Andrew Dunstan <andrew@dunslane.net>
On 19/05/26 22:00, Chao Li wrote:
> 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)
> ```
>
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
^ permalink raw reply [nested|flat] 6+ messages in thread
* Re: Avoid leaking system path from pg_available_extensions
2026-05-20 01:00 Avoid leaking system path from pg_available_extensions Chao Li <li.evan.chao@gmail.com>
2026-05-21 15:12 ` Re: Avoid leaking system path from pg_available_extensions Matheus Alcantara <matheusssilv97@gmail.com>
@ 2026-05-22 07:25 ` Jim Jones <jim.jones@uni-muenster.de>
2026-05-22 15:40 ` Re: Avoid leaking system path from pg_available_extensions Matheus Alcantara <matheusssilv97@gmail.com>
0 siblings, 1 reply; 6+ messages in thread
From: Jim Jones @ 2026-05-22 07:25 UTC (permalink / raw)
To: Matheus Alcantara <matheusssilv97@gmail.com>; Chao Li <li.evan.chao@gmail.com>; pgsql-hackers; +Cc: Andrew Dunstan <andrew@dunslane.net>
On 21/05/2026 17:12, Matheus Alcantara wrote:
> 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
^ permalink raw reply [nested|flat] 6+ messages in thread
* Re: Avoid leaking system path from pg_available_extensions
2026-05-20 01:00 Avoid leaking system path from pg_available_extensions Chao Li <li.evan.chao@gmail.com>
2026-05-21 15:12 ` Re: Avoid leaking system path from pg_available_extensions Matheus Alcantara <matheusssilv97@gmail.com>
2026-05-22 07:25 ` Re: Avoid leaking system path from pg_available_extensions Jim Jones <jim.jones@uni-muenster.de>
@ 2026-05-22 15:40 ` Matheus Alcantara <matheusssilv97@gmail.com>
0 siblings, 0 replies; 6+ messages in thread
From: Matheus Alcantara @ 2026-05-22 15:40 UTC (permalink / raw)
To: Jim Jones <jim.jones@uni-muenster.de>; Chao Li <li.evan.chao@gmail.com>; pgsql-hackers; +Cc: Andrew Dunstan <andrew@dunslane.net>
On 22/05/26 04:25, Jim Jones wrote:
> On 21/05/2026 17:12, Matheus Alcantara wrote:
>> I've reproduced the issue and the fix looks correct to me.
>
> same here, +1
>
Thank you for also testing.
> 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.
>
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
EDB: https://www.enterprisedb.com
^ permalink raw reply [nested|flat] 6+ messages in thread
end of thread, other threads:[~2026-05-22 15:40 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2026-05-20 01:00 Avoid leaking system path from pg_available_extensions Chao Li <li.evan.chao@gmail.com>
2026-05-20 01:07 ` Chao Li <li.evan.chao@gmail.com>
2026-05-21 08:55 ` lu feng <fnlo1995@gmail.com>
2026-05-21 15:12 ` Matheus Alcantara <matheusssilv97@gmail.com>
2026-05-22 07:25 ` Jim Jones <jim.jones@uni-muenster.de>
2026-05-22 15:40 ` Matheus Alcantara <matheusssilv97@gmail.com>
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox