Pgadmin4: remote code execution by an authenticated user
Description
A flaw was found in pgAdmin. This issue occurs when the pgAdmin server HTTP API validates the path a user selects to external PostgreSQL utilities such as pg_dump and pg_restore. Versions of pgAdmin prior to 7.6 failed to properly control the server code executed on this API, allowing an authenticated user to run arbitrary commands on the server.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
In pgAdmin versions before 7.6, an authenticated user can execute arbitrary commands via the validate_binary_path API due to insufficient path sanitization.
Vulnerability
Description
A flaw in pgAdmin's HTTP API allows authenticated users to execute arbitrary commands on the server. The vulnerable endpoint, validate_binary_path, is used to verify the path to external PostgreSQL utilities like pg_dump and pg_restore. Prior to version 7.6, the function did not properly sanitize user-supplied paths, directly passing them to subprocess.getoutput without adequate escaping. This enables command injection by crafting a malicious path [1][3].
Exploitation
Prerequisites
An attacker must be an authenticated user of the pgAdmin web interface. They can send a specially crafted request to the validate_binary_path endpoint, which is typically used during server configuration. The vulnerable code path used subprocess.getoutput with the user-controlled full_path variable, allowing arbitrary system commands to be injected. The commit fixing the issue (35f05e4) replaces this with a safer function get_binary_path_versions that validates paths before execution [3].
Impact
Successful exploitation grants the attacker arbitrary command execution on the pgAdmin server. This could lead to full compromise of the application, data theft, service disruption, or further lateral movement within the network. Given that pgAdmin is often deployed with elevated privileges to manage PostgreSQL instances, the impact is critical.
Mitigation
The vulnerability has been addressed in pgAdmin version 7.6. Users should upgrade to this version or later. The official repository commit [3] details the security fix, and updates have been released for affected distributions such as Fedora [4]. No workarounds are provided; upgrading is strongly recommended.
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
pgadmin4PyPI | < 7.7 | 7.7 |
Affected products
3- Range: REL-1_0, REL-1_0-BETA1, REL-1_0-BETA2, …
- ghsa-coords2 versions
< 7.7+ 1 more
- (no CPE)range: < 7.7
- (no CPE)range: < 7.8-1.1
Patches
135f05e49b363Fix the security issue of validate bin path to consider and fix more scenarios. #6763
2 files changed · +46 −50
web/pgadmin/misc/__init__.py+7 −30 modified@@ -13,7 +13,8 @@ from flask import url_for, render_template, Response, request, current_app from flask_babel import gettext from flask_security import login_required -from pgadmin.utils import PgAdminModule, replace_binary_path +from pgadmin.utils import PgAdminModule, replace_binary_path, \ + get_binary_path_versions from pgadmin.utils.csrf import pgCSRFProtect from pgadmin.utils.session import cleanup_session_files from pgadmin.misc.themes import get_all_themes @@ -254,37 +255,13 @@ def validate_binary_path(): version_str = '' if 'utility_path' in data and data['utility_path'] is not None: - # Check if "$DIR" present in binary path - binary_path = replace_binary_path(data['utility_path']) - - for utility in UTILITIES_ARRAY: - full_path = os.path.abspath( - os.path.join(binary_path, - (utility if os.name != 'nt' else - (utility + '.exe')))) - - try: - # if path doesn't exist raise exception - if not os.path.exists(binary_path): - current_app.logger.warning('Invalid binary path.') - raise Exception() - # escape double quotes to avoid command injection. - # Get the output of the '--version' command - version_string = \ - subprocess.getoutput(r'"{0}" --version'.format( - full_path.replace('"', '""'))) - # Get the version number by splitting the result string - version_string.split(") ", 1)[1].split('.', 1)[0] - except Exception: + binary_versions = get_binary_path_versions(data['utility_path']) + for utility, version in binary_versions.items(): + if version is None: version_str += "<b>" + utility + ":</b> " + \ "not found on the specified binary path.<br/>" - continue - - # Replace the name of the utility from the result to avoid - # duplicate name. - result_str = version_string.replace(utility, '') - - version_str += "<b>" + utility + ":</b> " + result_str + "<br/>" + else: + version_str += "<b>" + utility + ":</b> " + version + "<br/>" else: return precondition_required(gettext('Invalid binary path.'))
web/pgadmin/utils/__init__.py+39 −20 modified@@ -351,35 +351,54 @@ def get_server(sid): return server +def get_binary_path_versions(binary_path: str) -> dict: + ret = {} + binary_path = os.path.abspath( + replace_binary_path(binary_path) + ) + + for utility in UTILITIES_ARRAY: + ret[utility] = None + full_path = os.path.join(binary_path, + (utility if os.name != 'nt' else + (utility + '.exe'))) + + try: + # if path doesn't exist raise exception + if not os.path.isdir(binary_path): + current_app.logger.warning('Invalid binary path.') + raise Exception() + # Get the output of the '--version' command + cmd = subprocess.run( + [full_path, '--version'], + shell=False, + capture_output=True, + text=True + ) + if cmd.returncode == 0: + ret[utility] = cmd.stdout.split(") ", 1)[1].strip() + else: + raise Exception() + except Exception as _: + continue + + return ret + + def set_binary_path(binary_path, bin_paths, server_type, version_number=None, set_as_default=False): """ This function is used to iterate through the utilities and set the default binary path. """ path_with_dir = binary_path if "$DIR" in binary_path else None + binary_versions = get_binary_path_versions(binary_path) - # Check if "$DIR" present in binary path - binary_path = replace_binary_path(binary_path) - - for utility in UTILITIES_ARRAY: - full_path = os.path.abspath( - os.path.join(binary_path, (utility if os.name != 'nt' else - (utility + '.exe')))) - + for utility, version in binary_versions.items(): + version_number = version if version_number is None else version_number + if version_number.find('.'): + version_number = version_number.split('.', 1)[0] try: - # if version_number is provided then no need to fetch it. - if version_number is None: - # Get the output of the '--version' command - version_string = \ - subprocess.getoutput('"{0}" --version'.format(full_path)) - - # Get the version number by splitting the result string - version_number = \ - version_string.split(") ", 1)[1].split('.', 1)[0] - elif version_number.find('.'): - version_number = version_number.split('.', 1)[0] - # Get the paths array based on server type if 'pg_bin_paths' in bin_paths or 'as_bin_paths' in bin_paths: paths_array = bin_paths['pg_bin_paths']
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
9- github.com/advisories/GHSA-ghp8-52vx-77j4ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2023-5002ghsaADVISORY
- bugzilla.redhat.com/show_bug.cgighsaissue-trackingx_refsource_REDHATWEB
- github.com/pgadmin-org/pgadmin4/commit/35f05e49b3632a0a674b9b36535a7fe2d93dd0c2ghsaWEB
- github.com/pgadmin-org/pgadmin4/issues/6763ghsaWEB
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/2S24D3S2GVNGTDNE6SF2OQSOPU3H72UWghsaWEB
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/VIRTMQZEE6K7RD37ERZ2UFYFLEUXLQU3ghsaWEB
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/2S24D3S2GVNGTDNE6SF2OQSOPU3H72UW/mitre
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/VIRTMQZEE6K7RD37ERZ2UFYFLEUXLQU3/mitre
News mentions
0No linked articles in our index yet.