Skip to content

Commit 1d39739

Browse files
committed
Fixed remote code execution vulnerability when restoring PLAIN-format SQL dumps in server mode (CVE-2025-12762). #9320
1 parent ed52a44 commit 1d39739

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

docs/en_US/release_notes_9_10.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,5 @@ Bug fixes
4040
| `Issue #9233 <https://github.com/pgadmin-org/pgadmin4/issues/9233>`_ - Fixed an issue where the Select All option on the columns tab of import/export data was not working in languages other than English.
4141
| `Issue #9240 <https://github.com/pgadmin-org/pgadmin4/issues/9240>`_ - Fixed an issue where the Debian build process failed with a "Sphinx module not found" error when using a Python virtual environment.
4242
| `Issue #9281 <https://github.com/pgadmin-org/pgadmin4/issues/9281>`_ - Fixed an issue where the last used storage directory was reset to blank, leading to access denied errors during backup or restore operations.
43-
| `Issue #9304 <https://github.com/pgadmin-org/pgadmin4/issues/9304>`_ - Fixed an issue that prevented assigning multiple users to an RLS policy.
43+
| `Issue #9304 <https://github.com/pgadmin-org/pgadmin4/issues/9304>`_ - Fixed an issue that prevented assigning multiple users to an RLS policy.
44+
| `Issue #9320 <https://github.com/pgadmin-org/pgadmin4/issues/9320>`_ - Fixed remote code execution vulnerability when restoring PLAIN-format SQL dumps in server mode (CVE-2025-12762).

web/pgadmin/tools/restore/__init__.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"""Implements Restore Utility"""
1111

1212
import json
13+
import re
1314

1415
from flask import render_template, request, current_app, Response
1516
from flask_babel import gettext as _
@@ -374,7 +375,38 @@ def use_restore_utility(data, manager, server, driver, conn, filepath):
374375
return None, utility, args
375376

376377

378+
def has_meta_commands(path, chunk_size=8 * 1024 * 1024):
379+
"""
380+
Quickly detect lines starting with '\' in large SQL files.
381+
Works even when lines cross chunk boundaries.
382+
"""
383+
# Look for start-of-line pattern: beginning or after newline,
384+
# optional spaces, then backslash
385+
pattern = re.compile(br'(^|\n)[ \t]*\\')
386+
387+
with open(path, "rb") as f:
388+
prev_tail = b""
389+
while chunk := f.read(chunk_size):
390+
data = prev_tail + chunk
391+
392+
# Search for pattern
393+
if pattern.search(data):
394+
return True
395+
396+
# Keep a small tail to preserve line boundary context
397+
prev_tail = data[-10:] # keep last few bytes
398+
399+
return False
400+
401+
377402
def use_sql_utility(data, manager, server, filepath):
403+
# Check the meta commands in file.
404+
if has_meta_commands(filepath):
405+
return _("Restore blocked: the selected PLAIN SQL file contains psql "
406+
"meta-commands (for example \\! or \\i). For safety, "
407+
"pgAdmin does not execute meta-commands from PLAIN restores. "
408+
"Please remove meta-commands."), None, None
409+
378410
utility = manager.utility('sql')
379411
ret_val = does_utility_exist(utility)
380412
if ret_val:

0 commit comments

Comments
 (0)