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)

Open
#10,249 0 comments 1 reaction 0 assignees View on GitHub

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.json with "Shared": true to 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=True explicitly 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

  1. 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
    
  2. servers.json contains a server entry with "Shared": true and "PasswordExecCommand": "<cmd>"
  3. Log in as any non-admin OAuth user
  4. 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__.pyconnection_manager() and _restore_connections_from_session(): unconditional manager.passexec = None for non-owners
  • web/pgadmin/browser/server_groups/servers/__init__.py_set_valid_attr_value(): _owner_only_fields blocks non-owners from setting passexec_cmd on their SharedServer
  • web/pgadmin/browser/server_groups/servers/__init__.pycreate_shared_server(): seeds passexec_cmd=None with no path to set it legitimately

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.