Skip to content

Pass the target database to utilities as a quoted connection string - #10464

Open
dpage wants to merge 2 commits into
pgadmin-org:masterfrom
dpage:fix/issue-10463-service-dbname
Open

dpage wants to merge 2 commits into
pgadmin-org:masterfrom
dpage:fix/issue-10463-service-dbname

Conversation

@dpage

@dpage dpage commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Backup (objects), Restore, Maintenance and Import/Export passed the selected database in PGDATABASE, but libpq ranks a dbname in the server's service file above that variable, so with such a service file every job silently ran against the service file's database.

This passes the database as --dbname "dbname='<name>'" instead, built by a new database_conninfo() helper using psycopg's make_conninfo(). libpq never expands a dbname given inside a connection string, so the connection-string injection protection from 5082834 is kept, whilst an explicit --dbname beats the service file.

Test plan

  • Updated the unit tests for all four tools to expect the quoted --dbname argument (including the injection payload cases).
  • New utils/tests/test_database_conninfo.py: round-trips awkward names (spaces, quotes, backslashes, host=..., URIs) through libpq's parser, and connects with a service file whose dbname differs to confirm the chosen database wins.
  • backup, restore, maintenance and import_export test packages pass locally against PostgreSQL 18.

Closes #10463

Summary by CodeRabbit

  • Bug Fixes
    • Backup, restore, import/export, and maintenance operations now consistently use the selected database, including when its name contains spaces, quotes, or connection-string-like text.
    • Operations respect the configured database instead of allowing a service file’s database setting to override it.
    • The detailed Restore window now displays the escaped database name in the command, consistent with the Backup window.

Backup (objects), Restore, Maintenance and Import/Export passed the target
database in PGDATABASE, which libpq ranks below a dbname set in the
server's service file, so with such a service file every job ran against
the service file's database rather than the one selected.

Pass it instead as --dbname "dbname='<name>'". libpq never expands a
dbname given inside a connection string, so the protection against
connection-string injection is kept, and an explicit --dbname takes
precedence over the service file.

Closes pgadmin-org#10463
@coderabbitai

coderabbitai Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: pgadmin-org/pgadmin4/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 28c8ec28-3f67-4f69-81bd-e50e2c228695

📥 Commits

Reviewing files that changed from the base of the PR and between 826f7e6 and d39f69f.

📒 Files selected for processing (2)
  • web/pgadmin/utils/__init__.py
  • web/regression/feature_tests/pg_utilities_backup_restore_test.py

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 4 remain after this review.


Walkthrough

Backup, import/export, maintenance, and restore jobs pass the selected database as a quoted --dbname connection string. A shared helper builds that value. These jobs no longer set PGDATABASE to select the target database.

Changes

Utility database selection

Layer / File(s) Summary
Encode database names
web/pgadmin/utils/__init__.py, web/pgadmin/utils/tests/test_database_conninfo.py
database_conninfo() encodes a database name as a libpq dbname connection string. Tests cover special characters and a service file that sets dbname.
Pass the database to backup jobs
web/pgadmin/tools/backup/__init__.py, web/pgadmin/tools/backup/tests/test_backup_create_job_unit_test.py
Object backup commands pass the selected database through --dbname instead of PGDATABASE. Tests cover plain and connection-string-shaped names.
Pass the database to import/export and maintenance jobs
web/pgadmin/tools/import_export/__init__.py, web/pgadmin/tools/import_export/tests/test_import_export_create_job_unit_test.py, web/pgadmin/tools/maintenance/__init__.py, web/pgadmin/tools/maintenance/tests/test_maintenance_create_job_unit_test.py
Import/export and maintenance commands pass the database through --dbname and no longer set PGDATABASE. Tests check the command argument and its value.
Pass the database to restore jobs
web/pgadmin/tools/restore/__init__.py, web/pgadmin/tools/restore/tests/test_restore_create_job_unit_test.py, web/regression/feature_tests/pg_utilities_backup_restore_test.py
Restore and plain-SQL commands pass the database through --dbname and no longer set PGDATABASE. Tests cover both utility formats and check the displayed database name.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix · Severity of issue fixed: Medium

Suggested reviewers: asheshv

Merge Risk: ⚪ Minimal · up to d39f6

The utility jobs now explicitly target the selected database while preserving service-file settings. No actionable merge risk remains evident.

Security Architecture Review

Security architecture risk: 🔵 Low · up to d39f6

The selected database now takes precedence over the service file, while the database name is quoted to prevent it from supplying other connection settings. No introduced security issue was established, but execution and display behavior were not fully verified.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The affected security outcome is the database reached by a utility job using the configured server connection; the change applies across four utility areas, not to a new production public entrypoint.

Security Findings and Attack Paths

  • inferred — A connection-string-shaped database name is the relevant attacker-controlled input. Encoding it as one dbname value addresses the route by which a bare --dbname could redirect a utility connection; the available evidence does not establish an introduced bypass.

Trust Boundaries and Controls

  • observed — Batch-process environment setup still supplies the configured service name and password-related settings, while the changed jobs supply the database through --dbname. A new test specifies that the chosen database should win over a service-file dbname.
  • observed — The flagged public-API range changes a regression-test check of escaped process-detail HTML. It does not implement a production entrypoint; the check now expects the escaped database name in both backup and restore displayed commands.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 47.06% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 17 functions across 11 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: passing the selected database to utilities as a quoted connection string.
Linked Issues check ✅ Passed The changes address issue [#10463] for Backup (objects), Restore, Maintenance, and Import/Export. Each utility now passes the selected database through an explicit --dbname value created by `databas…
Out of Scope Changes check ✅ Passed The changes are limited to the four affected utilities, their automated tests, the shared database_conninfo() helper, helper tests, and the related backup/restore feature test. These changes directl…
  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…hange.

pgadmin.utils is imported by the documentation build, where libpq is not
installed, so import psycopg's make_conninfo lazily. The database name is
shown in the utility command again, so the XSS feature test once more
checks that it is escaped there, rather than that it is absent.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Utilities ignore the selected database when the server's service file sets dbname

1 participant