pgAdmin 4 in server mode had no data isolation between users — any
authenticated user could access other users' private servers,
background processes, and debugger state by guessing object IDs.
The shared server feature had 21 vulnerabilities including credential
leaks, privilege escalation via passexec_cmd, and owner data
corruption via SQLAlchemy session mutations.
Centralized access control:
- New server_access.py with get_server(), get_server_group(),
get_user_server_query() replacing ~20 unfiltered queries
- connection_manager() raises ObjectGone (HTTP 410) in server mode
when access is denied — fixes 155+ unguarded callers
- UserScopedMixin.for_user() on 10 models replaces scattered
user_id filters
Shared server isolation (all 21 audit issues):
- Expunge server from session before property merge to prevent
owner data corruption
- Suppress passexec_cmd, post_connection_sql for non-owners in
merge, API response, and ServerManager
- Override all 6 SSL/passfile connection_params keys from
SharedServer; strip owner-only keys; sanitize on creation
- _is_non_owner() helper centralises 15+ inline ownership checks
- SharedServer lookup uses (osid, user_id) not name
- Unique constraint on SharedServer(osid, user_id)
- Tunnel/DB password save, change_password, clear_saved_password,
clear_sshtunnel_password all branch on ownership
- Only owner can unshare (delete_shared_server guard)
- Session restore includes shared servers
- tunnel_port/tunnel_keep_alive copied from owner, not hardcoded
Tool/module hardening:
- All tool endpoints use get_server()
- Debugger function arguments scoped by user_id
- Background processes use Process.for_user()
- Workspace adhoc servers scoped to current user
Migration (schema version 49 -> 50):
- Add user_id to debugger_function_arguments composite PK
- Add indexes on server, sharedserver, servergroup
- Add unique constraint on sharedserver(osid, user_id)
The sslsni connection parameter was being stored as a boolean (true/false)
in the database, but libpq expects integer values (1/0) for this parameter.
When a boolean value was passed to libpq, it resulted in SSL connection
failures with 'unexpected eof while reading' errors.
This fix converts boolean connection parameters (sslcompression, sslsni) to
integers when creating the connection string in server_manager.py, ensuring
libpq receives the expected integer format.
Fixes connection issues when using PGSSLSNI=1 with PostgreSQL 14+ servers.
The new implementation will store the master password in the keyring instead of storing each and every server password separately. The master password will be used to encrypt/decrypt server password when storing in the pgAdmin config DB.
1) Do not use the Array index in keys.
2) Import from the same module should be merged.
3) Mutable variables should not be exported.
4) Variables should not be initialized to undefined.
5) startswith or endswith method should be used.
6) Unwrap this unnecessarily grouped subpattern.
Additionally, addressed many other SonarQube rules.
Fix an issue where queries longer than 1 minute get stuck - Container 7.1. #6317
Fix an issue where queries get stuck with auto-completion enabled. #6356
Fix an issue where queries can't complete execution. #6163