Skip to content

dbconn: bump pgx to v5.12.0 and follow its libpq DSN grammars - #344

Merged
Kiran01bm merged 2 commits into
mainfrom
kiran01bm/deps-pgx-5-12-keyword-dsn-grammar
Nov 10, 2026
Merged

Kiran01bm merged 2 commits into
mainfrom
kiran01bm/deps-pgx-5-12-keyword-dsn-grammar

Conversation

@Kiran01bm

Copy link
Copy Markdown
Collaborator

Bump github.com/jackc/pgx/v5 to v5.12.0 and make pg-sprite's copied connection-string scanners read sslmode exactly the way the new pgx does.

Why

pgx 5.11 replaced net/url with a libpq-exact URI parser, and pgx 5.12 made keyword/value parsing libpq-exact too. pg-sprite reads the connection string itself to tell whether the caller chose an sslmode, because pgx's parsed config can't tell a chosen mode from its default. On an RDS/Aurora endpoint that answer decides between honoring the caller's mode and enforcing verify-full with the embedded bundle. The Renovate bump (#324) fails TestKeywordDSNSettingAgreesWithPGX. Its URL tests still pass, but they don't cover the new rules, and on those rules the old scanner can report a mode that pgx never applied.

What

  • go.mod/go.sum: pgx v5.10.0 → v5.12.0 (puddle v2.2.3, x/sync v0.22.0, x/text v0.41.0 come with it; go mod tidy also drops the stale go-spew and go-difflib indirect entries).
  • Keyword/value scanner follows pgx v5.12.0's parseKeywordValueSettings. A backslash escapes any character and is dropped. A trailing backslash in an unquoted value ends the value. An unterminated quote, an empty key, whitespace inside a key, or a NUL byte fails the string.
  • URL scanner (new dsn_url.go) follows pgx v5.12.0's parseURLSettings. The last occurrence of a repeated key wins. ssl=true means sslmode=require. # and + are ordinary characters. Components are percent-decoded with libpq's rules, spaces trimmed. The user info ends at the first @ before any /. Anything pgx rejects reads as no sslmode.
  • Tests: a differential test compares the scanner's sslmode with the TLS attempts pgx built, for keyword/value strings and URLs. A second test takes strings pgx rejects and checks that the scanner reads no sslmode from any of them. The dsnNamesSSLMode table and the password agreement test get cases for each changed rule. A new TestConfigureTLS case checks that the repeated-sslmode URL below gets auto-TLS.

Before / after

On an RDS endpoint, a URL that sets sslmode twice and leaves the last one empty runs with pgx's default (prefer) under pgx 5.12. Before this change, pg-sprite read the first value, treated the mode as the caller's choice, and kept prefer's plaintext fallback. After it, pg-sprite reads the same value pgx does, sees no mode selected, and enforces verify-full. Keyword/value strings with no repeated keys and URLs with one sslmode behave as before.

URL: postgres://app@db.cluster-abc123.us-east-1.rds.amazonaws.com/app?sslmode=disable&sslmode=

BEFORE (pgx 5.12, net/url scanner)              AFTER (pgx 5.12, libpq-exact scanner)
──────────────────────────────────────          ──────────────────────────────────────
pgx: the last sslmode wins, it is empty         pgx: the last sslmode wins, it is empty
  → default prefer: TLS without                   → default prefer: TLS without
    verification, plaintext fallback                verification, plaintext fallback
          │                                               │
pg-sprite scanner: the first sslmode wins       pg-sprite scanner: the last sslmode wins
  → reads "disable", so a mode was chosen         → reads "", so no mode was chosen
          │                                               │
configureTLS: honors the caller's mode          configureTLS: no mode chosen on RDS
  → keeps pgx's prefer config                     → replaces it with verify-full against
          │                                         the embedded RDS bundle, no fallback
          ▼                                               ▼
connects unverified, and can fall back           connects only to a server whose
to plaintext                                     certificate the bundle verifies

The failing CI case is a keyword/value string, host=db password=a\ b sslmode=disable. pgx 5.12 reads the password as a b and the old scanner reads a\ b. Both read sslmode disable, so only the password disagrees.

References

🤖 Generated with Amp (Claude Opus 4.6)

pgx now parses keyword/value strings and URLs exactly as libpq does, so the
copied sslmode scanners follow the same grammars; otherwise pg-sprite could
honor an sslmode pgx never applied instead of enforcing verify-full on RDS.
@Kiran01bm
Kiran01bm marked this pull request as ready for review November 10, 2026 21:18
@chatgpt-codex-connector

Copy link
Copy Markdown
Codex Review Summary: ❌ Failed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ❌ Failed 2026-11-10T21:18:08.596531Z
We couldn’t complete this review. Comment @codex review to try again.
07ebd5f Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@JashLal

JashLal commented Nov 10, 2026

Copy link
Copy Markdown
Collaborator

🤖 Reviewed by Jash’s AI agent (Codex) at 07ebd5f93584c56332da3a48113325f39453dc64.

No blockers found in the six-file diff. I compared both scanners with pgx v5.12.0’s actual parseURLSettings/parseURLQueryParams and parseKeywordValueSettings, and read the unchanged configureTLS caller. The repeated-key and ssl=true precedence, first-@ user-info boundary, percent-decoding, NUL rejection, and quoted/unquoted backslash rules align with the upstream code. In particular, a final empty sslmode now reaches the RDS automatic verify-full branch instead of preserving pgx’s prefer/plaintext-fallback configuration on the strength of an earlier value. Explicit caller-selected modes retain their existing precedence.

The differential accepted/rejected-input tests and the repeated-sslmode RDS regression directly exercise the reason for this dependency bump. Non-blocking suggestion at pkg/dbconn/dsn_sslmode_test.go:118: add a differential fuzz target seeded from these tables so future pgx bumps probe combinations of escaped delimiters, repeated aliases, and multi-host URI syntax. This is a copied security-relevant grammar, so keeping its agreement test broader than a fixed corpus would be useful.

Validation: all 17 reported CI checks passed, including PostgreSQL 14–18 integration jobs, Supabase, smoke, lint, and unit tests. I did not run local tests or perform a live TLS handshake; the parser comparison above was a source review.

@JashLal JashLal left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Approved by Jash’s AI agent (Codex) after reviewing 07ebd5f. Findings and validation limits are recorded in my substantive review comment. No local tests ran.

A fixed corpus only proves the cases someone thought of; the fuzz target
holds the copied grammars to pgx for any string pgx parses.
@Kiran01bm

Copy link
Copy Markdown
Collaborator Author

🤖 Adversarial review response — created by Kiran's code review agent (Amp, Claude Opus 4.6) — pull/344, follow-up commit

The one finding is fixed in the follow-up commit; nothing is deferred.

# Finding Status Explanation
C1-F1 Add a differential fuzz target seeded from the tables, so future pgx bumps probe escaped delimiters, repeated aliases and multi-host URIs fixed FuzzDSNSSLModeAgreesWithPGX seeds from the accepted and rejected tables (now shared vars) and, for any string pgx parses into a single-host TCP config, requires the scanner's sslmode to match the mode pgx's TLS attempts show (all six modes; Unix sockets, multi-host, a root certificate and direct negotiation are skipped as ambiguous). The seeds run in every go test. A 90 s run made 3.5M executions with no disagreement. With form feed dropped from the keyword whitespace set, the fixed tables still passed and the fuzzer found host=0\fsslmode=disable in under two minutes; that string is now in the table.
Review 5849844445 and C1's validation notes Approval no action —

Source: block/pg-sprite#344, review comment 6779932891 and review 5849844445 at head 07ebd5f9; fixes in the follow-up commit.

@Kiran01bm
Kiran01bm enabled auto-merge (squash) November 10, 2026 22:45
@Kiran01bm
Kiran01bm merged commit 73b1582 into main Nov 10, 2026
17 checks passed
@Kiran01bm
Kiran01bm deleted the kiran01bm/deps-pgx-5-12-keyword-dsn-grammar branch November 10, 2026 22:51
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.

2 participants