pgadmin-org / pgadmin-org/pgadmin4
`PasswordExecCommand` silently ignored for shared-server non-owners in SERVER_MODE despite `ENABLE_SERVER_PASS_EXEC_CMD=True` (regression in 9.15)
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 3.8k
- Forks
- 891
- Avg merge
- 4d 7h
- Merged PRs (30d)
- 8
Description
pgAdmin version: 9.15
Regression from: 9.14
Deployment type: Container / SERVER_MODE with OAuth2
Description
Since 9.15 (PR #9830 / CVE-2026-7813), manager.passexec is unconditionally set to None for any non-owner of a shared server in connection_manager() and _restore_connections_from_session() in web/pgadmin/utils/driver/psycopg3/__init__.py:
if config.SERVER_MODE and server_data.shared and \
server_data.user_id != current_user.id:
manager.passexec = None # PasswordExecCommand never runs
This silently breaks any container deployment that:
- Uses
PGADMIN_SERVER_JSON_FILE/servers.jsonwith"Shared": trueto pre-configure servers for all OAuth users - Sets
"PasswordExecCommand"in the server definition to supply the shared DB user's password - Has
PGADMIN_CONFIG_ENABLE_SERVER_PASS_EXEC_CMD=Trueexplicitly configured by the system administrator
The ENABLE_SERVER_PASS_EXEC_CMD config flag is now meaningless for shared servers — it is checked on startup/UI but the suppression in connection_manager fires regardless, with no log message or error surfaced to the user. The connection silently has no password.
Expected behaviour
When ENABLE_SERVER_PASS_EXEC_CMD=True is explicitly set by the system administrator, PasswordExecCommand should be honoured for shared-server non-owners. The system admin has consciously opted into this feature and is responsible for the command's content — the privilege-escalation concern (malicious owner targeting users) does not apply when the admin and the server owner are the same entity (i.e., the deployment administrator).
A reasonable middle ground: honour passexec_cmd from the SharedServer record (already added as a column in #9835) for non-owners, while still blocking inheritance from the owner's Server record. Currently _owner_only_fields prevents non-owners from ever setting passexec_cmd on their SharedServer via the API, and create_shared_server() seeds it as None, making the new column unreachable.
Steps to reproduce
- Deploy pgAdmin container with:
PGADMIN_CONFIG_SERVER_MODE=True PGADMIN_CONFIG_ENABLE_SERVER_PASS_EXEC_CMD=True PGADMIN_SERVER_JSON_FILE=/path/to/servers.json servers.jsoncontains a server entry with"Shared": trueand"PasswordExecCommand": "<cmd>"- Log in as any non-admin OAuth user
- Attempt to connect to the shared server
Result: The exec command is never run; the connection has no password and fails (or prompts interactively).
Expected: The exec command runs and supplies the password, as it did in 9.14.
Relevant source locations
web/pgadmin/utils/driver/psycopg3/__init__.py—connection_manager()and_restore_connections_from_session(): unconditionalmanager.passexec = Nonefor non-ownersweb/pgadmin/browser/server_groups/servers/__init__.py—_set_valid_attr_value():_owner_only_fieldsblocks non-owners from settingpassexec_cmdon their SharedServerweb/pgadmin/browser/server_groups/servers/__init__.py—create_shared_server(): seedspassexec_cmd=Nonewith no path to set it legitimately
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read connection_manager() and _restore_connections_from_session() in web/pgadmin/utils/driver/psycopg3/init.py, then trace _set_valid_attr_value() and create_shared_server() in web/pgadmin/browser/server_groups/servers/init.py. Verify the relevant shared-server data path and add regression coverage so an explicitly enabled PasswordExecCommand works for non-owner shared-server connections without restoring blocked owner-record inheritance.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- postgresql, python
- Domain
- authentication, backend, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 58/100