Skip to content

Import CVE-2025-8714 and CVE-2026-18408 fixes from upstream (4240405, df245c3, bc18487) - #28

Open
abhinab-yb wants to merge 3 commits into
yugabyte:yb-pg15from
abhinab-yb:import-cve-2025-8714
Open

Import CVE-2025-8714 and CVE-2026-18408 fixes from upstream (4240405, df245c3, bc18487)#28
abhinab-yb wants to merge 3 commits into
yugabyte:yb-pg15from
abhinab-yb:import-cve-2025-8714

Conversation

@abhinab-yb

@abhinab-yb abhinab-yb commented Aug 26, 2026

Copy link
Copy Markdown

Imports three upstream commits onto yb-pg15. Each commit in this PR carries its full upstream message.

Upstream Title CVE
postgres/postgres@4240405 Restrict psql meta-commands in plain-text dumps. CVE-2025-8714
postgres/postgres@df245c3 psql: Don't do backquote expansion in \unrestrict. CVE-2026-18408
postgres/postgres@bc18487 psql: Fix psql slash option leaks -

The third commit fixes a leak in the same code. It is not a CVE. Each commit is the REL_15_STABLE back-patch, not the
master commit.

All conflicts came from the first commit. The other two applied cleanly. The section below is the Conflicts resolved:
block from that commit's message, quoted as it stands there.

Conflicts resolved:

  • doc/src/sgml/ref/pg_restore.sgml:

    • the option list, between --no-tablespaces and --section:
      • Upstream inserts a --restrict-key=restrict_key entry there.
      • YB 2a5f853 cherry-picks master commit 1fd1bd8, which inserts --with-data, --with-schema and --with-statistics entries starting at he same opening tag, so the two share an unclosed
        element.
      • Keep both: YB's three entries first, then upstream's --restrict-key entry, each in its own .
  • src/bin/pg_dump/pg_backup.h:

    • last member of RestoreOptions and of _dumpOptions:
      • Upstream appends "char *restrict_key;" as the final member of each struct.
      • YB 2a5f853 appends a "flags derived from the user-settable flags" block (dumpSchema, dumpData, dumpStatistics) at the same position in both structs.
      • Keep both blocks, YB's first and restrict_key last.
  • src/bin/pg_dump/pg_dump.c:

    • the long-option switch in main():
      • Upstream adds "case 25:" for --restrict-key immediately after case 11.
      • YB 2a5f853 and b84ef44 fill that gap with cases 18 through 24 for the statistics-related options.
      • Keep YB's cases 18-24 and append upstream's case 25 after them; option code 25 does not collide, as YB's highest is 24.
  • src/bin/pg_dump/pg_dumpall.c:

    • last entry of long_options[]:
      • Upstream adds {"restrict-key", required_argument, NULL, 9}.
      • YB 2a5f853 adds {"statistics-only", no_argument, &statistics_only, 1} on the same final line.
      • Keep both; code 9 is free, as YB's numeric codes stop at 7.
  • src/bin/pg_dump/pg_restore.c:

    • last entries of long_options[]:
      • Upstream adds {"restrict-key", required_argument, NULL, 6}.
      • YB b84ef44 and 2a5f853 add no-statistics, with-data, with-schema, with-statistics and statistics-only in the same slot.
      • Keep both; code 6 is free, as YB's numeric codes stop at 3.
  • src/test/recovery/t/027_stream_regress.pl:

    • the pg_dumpall argument lists for the primary and standby dumps:
      • Upstream adds '--restrict-key=test' before '--no-sync' so the two dumps compare byte for byte.
      • YB 2a5f853 adds '--no-statistics' onto the same line as '--no-sync' and '-p'.
      • Keep both arguments, reflowed onto separate lines.
  • src/bin/pg_dump/t/002_pg_dump.pl:

    • the test-definition validation loop:
      • Upstream adds two %tests entries, "restrict" and "unrestrict", that set "all_runs => 1" and define no "like" list, and teaches the run loop to honour "all_runs". The REL_15_STABLE back-patch stops there, because upstream REL_15_STABLE has no check that requires "like". That check exists only on master. 41a2844 "Clean up some pg_dump tests" added it as a test cleanup, and upstream never back-patched it; no commit on REL_15_STABLE has ever introduced it.
      • yb-pg15 is REL_15_STABLE plus selected master cherry-picks, and e9c1b29 is one of them: YB's cherry-pick of 41a2844. yb-pg15 therefore does carry the check, and it dies with 'missing "like" in test ""' for any entry that defines no "like" list. The two edits sit about 3,800 lines apart and never touch the same lines, so git merged them with no textual conflict. The breakage surfaced only when 002_pg_dump.pl ran and died.
      • Take the corresponding hunk from master commit 71ea0d6, the master version of this same fix, which relaxes the check to accept "all_runs" in place of "like". Master's changes to this file and the back-patch's are otherwise identical. The hunk is missing from the back-patch only because REL_15_STABLE had no check to relax, and yb-pg15 has one. It is the only part of 71ea0d6 that applies here. The rest is master-only: src/bin/pg_combinebackup (absent in 15); src/bin/psql/tab-complete.in.c (master renamed the file, and 15 has tab-complete.c, which the back-patch already covers); two attributes in psql-ref.sgml; an #include "dumputils.h" that pg_restore.c already has on this branch; and one extra '--restrict-key=test' argument to the pg_dumpall call in pg_upgrade's TAP test.

Test Plan:

Suite Result
make check (regress) All 214 tests passed
make -C src/bin/pg_dump check Files=5, Tests=9484, Result: PASS
make -C src/bin/psql check Files=3, Tests=70, Result: PASS
make -C contrib check 139 regress, 364 TAP, all passed
make -C src/test/isolation check All 114 tests passed
make -C src/test/modules check 51 regress, 2314 TAP, all passed

nathan-bossart and others added 3 commits August 26, 2026 13:04
A malicious server could inject psql meta-commands into plain-text
dump output (i.e., scripts created with pg_dump --format=plain,
pg_dumpall, or pg_restore --file) that are run at restore time on
the machine running psql.  To fix, introduce a new "restricted"
mode in psql that blocks all meta-commands (except for \unrestrict
to exit the mode), and teach pg_dump, pg_dumpall, and pg_restore to
use this mode in plain-text dumps.

While at it, encourage users to only restore dumps generated from
trusted servers or to inspect it beforehand, since restoring causes
the destination to execute arbitrary code of the source superusers'
choice.  However, the client running the dump and restore needn't
trust the source or destination superusers.

Reported-by: Martin Rakhmanov
Reported-by: Matthieu Denais <litezeraw@gmail.com>
Reported-by: RyotaK <ryotak.mail@gmail.com>
Suggested-by: Tom Lane <tgl@sss.pgh.pa.us>
Reviewed-by: Noah Misch <noah@leadboat.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Reviewed-by: Peter Eisentraut <peter@eisentraut.org>
Security: CVE-2025-8714
Backpatch-through: 13
(cherry picked from commit 4240405)

Conflicts resolved:

- doc/src/sgml/ref/pg_restore.sgml:
  - the option <varlistentry> list, between --no-tablespaces and --section:
    - Upstream inserts a --restrict-key=restrict_key entry there.
    - YB 2a5f853 cherry-picks master commit 1fd1bd8, which inserts
      --with-data, --with-schema and --with-statistics entries starting at
      the same <varlistentry> opening tag, so the two share an unclosed
      element.
    - Keep both: YB's three entries first, then upstream's --restrict-key
      entry, each in its own <varlistentry>.

- src/bin/pg_dump/pg_backup.h:
  - last member of RestoreOptions and of _dumpOptions:
    - Upstream appends "char *restrict_key;" as the final member of each
      struct.
    - YB 2a5f853 appends a "flags derived from the user-settable flags"
      block (dumpSchema, dumpData, dumpStatistics) at the same position in
      both structs.
    - Keep both blocks, YB's first and restrict_key last.

- src/bin/pg_dump/pg_dump.c:
  - the long-option switch in main():
    - Upstream adds "case 25:" for --restrict-key immediately after case 11.
    - YB 2a5f853 and b84ef44 fill that gap with cases 18 through 24
      for the statistics-related options.
    - Keep YB's cases 18-24 and append upstream's case 25 after them; option
      code 25 does not collide, as YB's highest is 24.

- src/bin/pg_dump/pg_dumpall.c:
  - last entry of long_options[]:
    - Upstream adds {"restrict-key", required_argument, NULL, 9}.
    - YB 2a5f853 adds {"statistics-only", no_argument, &statistics_only, 1}
      on the same final line.
    - Keep both; code 9 is free, as YB's numeric codes stop at 7.

- src/bin/pg_dump/pg_restore.c:
  - last entries of long_options[]:
    - Upstream adds {"restrict-key", required_argument, NULL, 6}.
    - YB b84ef44 and 2a5f853 add no-statistics, with-data, with-schema,
      with-statistics and statistics-only in the same slot.
    - Keep both; code 6 is free, as YB's numeric codes stop at 3.

- src/test/recovery/t/027_stream_regress.pl:
  - the pg_dumpall argument lists for the primary and standby dumps:
    - Upstream adds '--restrict-key=test' before '--no-sync' so the two dumps
      compare byte for byte.
    - YB 2a5f853 adds '--no-statistics' onto the same line as '--no-sync'
      and '-p'.
    - Keep both arguments, reflowed onto separate lines.

- src/bin/pg_dump/t/002_pg_dump.pl:
  - the test-definition validation loop:
    - Upstream adds two %tests entries, "restrict" and "unrestrict", that set
      "all_runs => 1" and define no "like" list, and teaches the run loop to
      honour "all_runs".  The REL_15_STABLE back-patch stops there, because
      upstream REL_15_STABLE has no check that requires "like".  That check
      exists only on master.  41a2844 "Clean up some pg_dump tests" added
      it as a test cleanup, and upstream never back-patched it; no commit on
      REL_15_STABLE has ever introduced it.
    - yb-pg15 is REL_15_STABLE plus selected master cherry-picks, and
      e9c1b29 is one of them: YB's cherry-pick of 41a2844.  yb-pg15
      therefore does carry the check, and it dies with
      'missing "like" in test "<name>"' for any entry that defines no "like"
      list.  The two edits sit about 3,800 lines apart and never touch the
      same lines, so git merged them with no textual conflict.  The breakage
      surfaced only when 002_pg_dump.pl ran and died.
    - Take the corresponding hunk from master commit 71ea0d6, the master
      version of this same fix, which relaxes the check to accept "all_runs"
      in place of "like".  Master's changes to this file and the back-patch's
      are otherwise identical.  The hunk is missing from the back-patch only
      because REL_15_STABLE had no check to relax, and yb-pg15 has one.  It is
      the only part of 71ea0d6 that applies here.  The rest is master-only:
      src/bin/pg_combinebackup (absent in 15); src/bin/psql/tab-complete.in.c
      (master renamed the file, and 15 has tab-complete.c, which the
      back-patch already covers); two <varlistentry id=...> attributes in
      psql-ref.sgml; an #include "dumputils.h" that pg_restore.c already has
      on this branch; and one extra '--restrict-key=test' argument to the
      pg_dumpall call in pg_upgrade's TAP test.
This oversight in commit 71ea0d6 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
(cherry picked from commit df245c3)
psql_scan_slash_option() returns a malloc'd string, but \getresults,
\gset in pipeline mode, \restrict, and \unrestrict did not free it
after consuming or copying the value.

Free these option strings after use.

Backpatch to all supported versions. In v17 and older, only \restrict
and \unrestrict are affected, so those branches need only that part of
the fix.

Author: Fujii Masao <masao.fujii@gmail.com>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Discussion: https://postgr.es/m/CAHGQGwEh3R3=1tx_a5=fTDJ+ycuwxWMEn6bG_Yt4B5P+hE7AVw@mail.gmail.com
Backpatch-through: 14
(cherry picked from commit bc18487)
@abhinab-yb
abhinab-yb requested a review from jasonyb August 26, 2026 07:49
@jasonyb

jasonyb commented Aug 27, 2026

Copy link
Copy Markdown

approved

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants