From a7e74a6ed685bc34e1f77a8b6a94d00fa3dff815 Mon Sep 17 00:00:00 2001 From: Dave Page Date: Tue, 16 Jun 2026 16:49:49 +0100 Subject: [PATCH] Re-home adhoc cloned servers to the calling user When /misc/workspace/adhoc_connect_server is given a sid, it clones the existing server. Server.clone() copies every column of the source row, including user_id, shared and shared_username. When a non-owner triggered an adhoc connect against an administrator-owned shared server, the clone inherited the administrator's ownership and shared flag, so pgAdmin persisted a new, administrator-owned, shared adhoc server row created at the behest of another user; the row is committed before the connection is attempted, so it survived even when the connection failed. Force the cloned adhoc record to belong to the current user and to be private (user_id, shared, shared_username) before committing, mirroring the new-server branch, so a non-owner can no longer persist a cross-tenant server record. --- web/pgadmin/misc/workspaces/__init__.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/web/pgadmin/misc/workspaces/__init__.py b/web/pgadmin/misc/workspaces/__init__.py index a5ae5c662..b3193a2bc 100644 --- a/web/pgadmin/misc/workspaces/__init__.py +++ b/web/pgadmin/misc/workspaces/__init__.py @@ -176,6 +176,17 @@ def adhoc_connect_server(): # Clone the server object server = server.clone() + # Server.clone() copies every column from the source row, + # including user_id/shared/shared_username. When the source + # is another user's shared server, the clone must not inherit + # that ownership: force the new adhoc record to belong to the + # current user and to be private, otherwise a non-owner ends + # up persisting a cross-tenant, administrator-owned server + # row. + server.user_id = current_user.id + server.shared = False + server.shared_username = None + # Replace the following with the new/changed value. server.maintenance_db = new_db server.username = new_username