1
0
mirror of https://github.com/postgres/postgres.git synced 2026-10-23 13:29:09 +03:00

psql: Don't do backquote expansion in \unrestrict.

This oversight in commit 71ea0d6795 allows a malicious server to
inject shell commands into plain-text dump output that are run at
restore time on the machine running psql.  To fix, interpret all
text after \unrestrict until the end of the line as its argument.

Reported-by: Lucas Velgus <velgusgus599@gmail.com>
Reported-by: Filip Janus <fjanus@redhat.com>
Reported-by: Daniel Bakker <daniel@jackds.nl>
Author: Nathan Bossart <nathandbossart@gmail.com>
Reviewed-by: Robert Haas <robertmhaas@gmail.com>
Reviewed-by: Noah Misch <noah@leadboat.com>
Security: CVE-2026-18408
Backpatch-through: 14
This commit is contained in:
Nathan Bossart
2026-08-10 06:38:06 -07:00
committed by Noah Misch
parent d97b3f58c1
commit 0119aa30e0
3 changed files with 20 additions and 2 deletions

View File

@@ -3859,6 +3859,11 @@ SELECT 1 \bind \sendpipeline
<application>pg_dumpall</application>, and
<application>pg_restore</application>, but it may be useful elsewhere.
</para>
<para>
Unlike most other meta-commands, the entire remainder of the line is
always taken to be the argument of <command>\unrestrict</command>, and
neither variable interpolation nor backquote expansion are performed.
</para>
</listitem>
</varlistentry>

View File

@@ -2790,6 +2790,12 @@ exec_command_restrict(PsqlScanState scan_state, bool active_branch,
Assert(!restricted);
/*
* Unlike \unrestrict, this argument may safely undergo backquote and
* variable expansion: HandleSlashCmds() rejects \restrict in
* restricted mode before its argument is scanned, so we only get here
* when the input could execute such things anyway.
*/
opt = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true);
if (opt == NULL || opt[0] == '\0')
{
@@ -3198,7 +3204,7 @@ exec_command_unrestrict(PsqlScanState scan_state, bool active_branch,
{
char *opt;
opt = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true);
opt = psql_scan_slash_option(scan_state, OT_WHOLE_LINE, NULL, true);
if (opt == NULL || opt[0] == '\0')
{
pg_log_error("\\%s: missing required argument", cmd);
@@ -3222,7 +3228,7 @@ exec_command_unrestrict(PsqlScanState scan_state, bool active_branch,
}
}
else
ignore_slash_options(scan_state);
ignore_slash_whole_line(scan_state);
return PSQL_CMD_SKIP_LINE;
}

View File

@@ -540,4 +540,11 @@ psql_fails_like(
qr/backslash commands are restricted; only \\unrestrict is allowed/,
'meta-command in restrict mode fails');
psql_fails_like(
$node,
qq{\\restrict test
\\unrestrict `echo test`},
qr/wrong key/,
'\unrestrict does not do backquote expansion');
done_testing();