Commit b4b897a
committed
fix: enforce data isolation and harden shared servers in server mode
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 (21 audit issues) leaked owner credentials,
saved passwords to wrong records, and corrupted owner data via
SQLAlchemy session mutations.
Centralized access control:
- New server_access.py with get_server(), get_server_group(),
get_user_server_query() replacing ~20 scattered unfiltered queries
- connection_manager() raises ObjectGone (HTTP 410) instead of
returning None — fixes 155+ unguarded callers at the chokepoint
- UserScopedMixin.for_user() on 10 models replaces scattered
user_id=current_user.id filters
Shared server isolation (addresses all 21 audit issues):
- get_shared_server_properties() expunges server from session
before mutation, preventing owner data corruption
- Suppresses passexec_cmd, post_connection_sql for non-owners
(merge function + API response + ServerManager)
- Overrides all 6 SSL/passfile connection_params keys from
SharedServer; strips owner-only keys non-owner hasn't set
- Sanitizes connection_params on SharedServer creation (strips
owner file paths)
- Tunnel/DB password save branches on ownership
- change_password() checks SharedServer.password for non-owners
- clear_saved/sshtunnel_password() use get_shared_server()
- update_connection_parameter() routes to SharedServer copy
- Only owner can trigger delete_shared_server (unshare)
- SharedServer lookup uses (osid, user_id) not name (Issue 20)
- Unique constraint on SharedServer(osid, user_id) with migration
- Session restore includes shared servers
- wal_replay()/check_pgpass() use get_server() for shared access
- _is_non_owner() helper eliminates 15+ repeated inline checks
- SENSITIVE_CONN_KEYS module-level constant (DRY)
- tunnel_port/tunnel_keep_alive copied from owner (not hardcoded)
- delete_shared_server() accepts user_id parameter
Tool/module hardening:
- All tool endpoints (sqleditor, schema_diff, psql, erd, backup,
restore, maintenance, import_export, debugger) use get_server()
- Debugger function arguments scoped by user_id (migration + model)
- Background processes use Process.for_user()
- Workspace adhoc servers scoped by user_id
- disconnect_from_all_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 for user_id
- Add unique constraint on sharedserver(osid, user_id)
- Fix ca00ec32581b to use raw SQL (model-independent)1 parent 872d5ac commit b4b897a
File tree
21 files changed
+914
-310
lines changed- web
- migrations/versions
- pgadmin
- browser/server_groups
- servers
- databases
- schemas/views
- misc
- bgprocess
- cloud
- workspaces
- model
- tools
- debugger
- erd
- import_export
- psql
- schema_diff
- sqleditor
- user_management
- utils
- driver/psycopg3
21 files changed
+914
-310
lines changedLines changed: 149 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
18 | | - | |
19 | | - | |
20 | 18 | | |
21 | 19 | | |
22 | 20 | | |
| |||
26 | 24 | | |
27 | 25 | | |
28 | 26 | | |
29 | | - | |
30 | | - | |
31 | | - | |
32 | | - | |
33 | | - | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
34 | 31 | | |
35 | 32 | | |
36 | 33 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
| 28 | + | |
| 29 | + | |
28 | 30 | | |
29 | 31 | | |
30 | 32 | | |
| |||
286 | 288 | | |
287 | 289 | | |
288 | 290 | | |
289 | | - | |
| 291 | + | |
290 | 292 | | |
291 | 293 | | |
292 | 294 | | |
| |||
296 | 298 | | |
297 | 299 | | |
298 | 300 | | |
299 | | - | |
| 301 | + | |
| 302 | + | |
300 | 303 | | |
301 | 304 | | |
302 | 305 | | |
| |||
373 | 376 | | |
374 | 377 | | |
375 | 378 | | |
376 | | - | |
377 | | - | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
378 | 382 | | |
379 | 383 | | |
380 | 384 | | |
| |||
383 | 387 | | |
384 | 388 | | |
385 | 389 | | |
386 | | - | |
387 | | - | |
388 | | - | |
389 | | - | |
390 | | - | |
391 | | - | |
392 | | - | |
393 | | - | |
394 | | - | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
395 | 398 | | |
396 | | - | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
397 | 402 | | |
398 | 403 | | |
399 | 404 | | |
| |||
421 | 426 | | |
422 | 427 | | |
423 | 428 | | |
424 | | - | |
| 429 | + | |
425 | 430 | | |
426 | 431 | | |
427 | 432 | | |
| |||
0 commit comments