Skip to content

fix(pg-connection-string): keep a literal + in query parameter values - #3846

Open
mmporong wants to merge 1 commit into
brianc:masterfrom
mmporong:pg-connection-string-plus
Open

mmporong wants to merge 1 commit into
brianc:masterfrom
mmporong:pg-connection-string-plus

Conversation

@mmporong

@mmporong mmporong commented Nov 3, 2026 •

Copy link
Copy Markdown

parse() reads query parameters with URLSearchParams, which decodes them as form data, so a + in a value becomes a space:

parse('postgres://h/d?password=a+b').password          // 'a b'
parse('postgres://h/d?application_name=a+b').application_name // 'a b'

libpq only percent-decodes URI values (conninfo_uri_decode in src/interfaces/libpq/fe-connect.c copies every character other than a %XX escape as is), so for libpq the password in postgres://h/d?password=a+b is a+b. The README also says the other query parameters are "preserved intact". This affects every generic query parameter (user, password, application_name, options, ...), so a password with a + given as a query parameter fails to authenticate.

The fix escapes + before building the URLSearchParams for the generic parameters, so values are only percent-decoded. A space can still be written as %20 (or %2B for an explicit plus, as before). The socket: branch, where the README says db is urlencoded, is unchanged.

Compatibility: this changes the result for connection strings that use + to mean a space in a query value: they now get a literal +, as libpq does. If you would rather ship this in a major version or behind an option, I can adjust it.

Tests: a new case in test/parse.ts checks application_name, user, password and options with + and with %2B/%20. It fails before the change ('a b' instead of 'a+b') and passes after it. In packages/pg-connection-string, mocha passes (81 tests) with 100% statement/branch/function/line coverage under nyc, and eslint (repository config with prettier) is clean on both files. I did not run the other packages' tests.

URLSearchParams decodes query strings as form data, so a + in a query
value became a space: postgres://h/d?password=a+b gave the password
'a b', while libpq only percent-decodes and uses 'a+b'. Read the query
parameters with + escaped first. A space can still be written as %20.
@mmporong
mmporong requested a review from hjr3 as a code owner November 3, 2026 01:30
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.

1 participant