From 1d397395f75320ca1d4ed5e9ca721c603415e836 Mon Sep 17 00:00:00 2001 From: Akshay Joshi Date: Mon, 10 Nov 2025 11:13:44 +0530 Subject: [PATCH] Fixed remote code execution vulnerability when restoring PLAIN-format SQL dumps in server mode (CVE-2025-12762). #9320 --- docs/en_US/release_notes_9_10.rst | 3 ++- web/pgadmin/tools/restore/__init__.py | 32 +++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/docs/en_US/release_notes_9_10.rst b/docs/en_US/release_notes_9_10.rst index adc5d5777..7dc0b6f98 100644 --- a/docs/en_US/release_notes_9_10.rst +++ b/docs/en_US/release_notes_9_10.rst @@ -40,4 +40,5 @@ Bug fixes | `Issue #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. | `Issue #9240 `_ - Fixed an issue where the Debian build process failed with a "Sphinx module not found" error when using a Python virtual environment. | `Issue #9281 `_ - Fixed an issue where the last used storage directory was reset to blank, leading to access denied errors during backup or restore operations. - | `Issue #9304 `_ - Fixed an issue that prevented assigning multiple users to an RLS policy. \ No newline at end of file + | `Issue #9304 `_ - Fixed an issue that prevented assigning multiple users to an RLS policy. + | `Issue #9320 `_ - Fixed remote code execution vulnerability when restoring PLAIN-format SQL dumps in server mode (CVE-2025-12762). \ No newline at end of file diff --git a/web/pgadmin/tools/restore/__init__.py b/web/pgadmin/tools/restore/__init__.py index 45d3d6393..93e3cfbe7 100644 --- a/web/pgadmin/tools/restore/__init__.py +++ b/web/pgadmin/tools/restore/__init__.py @@ -10,6 +10,7 @@ """Implements Restore Utility""" import json +import re from flask import render_template, request, current_app, Response from flask_babel import gettext as _ @@ -374,7 +375,38 @@ def use_restore_utility(data, manager, server, driver, conn, filepath): return None, utility, args +def has_meta_commands(path, chunk_size=8 * 1024 * 1024): + """ + Quickly detect lines starting with '\' in large SQL files. + Works even when lines cross chunk boundaries. + """ + # Look for start-of-line pattern: beginning or after newline, + # optional spaces, then backslash + pattern = re.compile(br'(^|\n)[ \t]*\\') + + with open(path, "rb") as f: + prev_tail = b"" + while chunk := f.read(chunk_size): + data = prev_tail + chunk + + # Search for pattern + if pattern.search(data): + return True + + # Keep a small tail to preserve line boundary context + prev_tail = data[-10:] # keep last few bytes + + return False + + def use_sql_utility(data, manager, server, filepath): + # Check the meta commands in file. + if has_meta_commands(filepath): + return _("Restore blocked: the selected PLAIN SQL file contains psql " + "meta-commands (for example \\! or \\i). For safety, " + "pgAdmin does not execute meta-commands from PLAIN restores. " + "Please remove meta-commands."), None, None + utility = manager.utility('sql') ret_val = does_utility_exist(utility) if ret_val: