Skip to content

Mask credentials embedded in JDBC URL authority - #2416

Open
fudianchn wants to merge 1 commit into
brettwooldridge:devfrom
fudianchn:mask-url-authority-credentials
Open

Mask credentials embedded in JDBC URL authority#2416
fudianchn wants to merge 1 commit into
brettwooldridge:devfrom
fudianchn:mask-url-authority-credentials

Conversation

@fudianchn

@fudianchn fudianchn commented Aug 7, 2026

Copy link
Copy Markdown

AI disclosure: this change was prepared with AI coding agents, reviewed and revised line by line by me.

Problem

UtilityElf.maskPasswordInJdbcUrl() only masks the password query parameter (?password=secret), but misses credentials embedded in the URL authority (user:password@host):

jdbc:postgresql://admin:s3cret@db.internal:5432/prod   → NOT masked

The existing pattern ([?&;][^&#;=]*[pP]password=)[^&#;]* requires a leading ?, &, or ; delimiter, so the userinfo password is never matched and is logged verbatim at DEBUG level via HikariConfig.logConfiguration() (and DriverDataSource). Reported in #2413.

Fix

Add a second pattern that masks the secret following the first colon of the userinfo, anchored on :// and terminated by @:

Pattern.compile("(://[^/?#@:]*:)[^/?#@]*(@)")
  • Username is preserved (e.g. admin:s3cret@admin:<masked>@), consistent with the existing query-parameter masking that keeps the password= key and masks only the value.
  • host:port without userinfo is not touched: the password component is delimited by the RFC 3986 reserved delimiters /, ?, #, @, so ://host:5432 never matches and a query value containing an at-sign (e.g. jdbc:mysql://host:3306/db?user=admin@corp.com, common for cloud databases with e-mail-style usernames) is never swallowed.
  • An empty username (://:password@host) is masked as well.
  • Boundary: passwords containing a raw /, ?, # or a second @ (all invalid unencoded per RFC 3986) cannot be told apart from path/query content by a regex over the URL string and are therefore left unmasked; percent-encode them (%2F, %3F, %23, %40) and they are masked. A URI-parsing approach could resolve the ambiguity, at the cost of rejecting the non-standard JDBC URL schemes; kept the regex for consistency with the existing query-parameter masking.

Verification

UtilityElfTest now covers: query-param regression, authority masking, both combined, port preservation, no false mask without userinfo, at-sign-in-query not swallowed, empty username masked, first-colon convention, and the reserved-delimiter boundary. Local run (JDK 21, JaCoCo skipped, 0.8.8 predates JDK 21): 14/14 tests pass.

jdbc:postgresql://admin:s3cret@db.internal:5432/prod   → jdbc:postgresql://admin:<masked>@db.internal:5432/prod
jdbc:postgresql://user:pass@host/db?password=other     → jdbc:postgresql://user:<masked>@host/db?password=<masked>
jdbc:mysql://user:pass@host:3306/db                    → jdbc:mysql://user:<masked>@host:3306/db
jdbc:postgresql://:secret@host:5432/db                 → jdbc:postgresql://:<masked>@host:5432/db
jdbc:postgresql://host:5432/db?user=admin              → (unchanged)
jdbc:mysql://host:3306/db?user=admin@corp.com          → (unchanged)

Alternative considered

Mask the entire userinfo (user:pass@<masked>@) for maximal secrecy. I kept the username visible to stay consistent with the existing "mask the secret, keep the structure" behaviour and to preserve useful logging context. Happy to switch to full userinfo masking if that's preferred.

Related: #2415

#2415 addresses the same issue with a nearly identical approach (second regex chained after the existing query-parameter mask). Both PRs use [^@]+ for the password segment. The remaining differences are minor:

Happy to defer to the maintainer on which to merge.

Fixes #2413.

@fudianchn
fudianchn force-pushed the mask-url-authority-credentials branch from d427b9a to dea2c2c Compare August 13, 2026 02:59
maskPasswordInJdbcUrl() only masked the password query parameter
(e.g. ?password=secret) but missed credentials embedded in the URL
authority (e.g. jdbc:postgresql://user:password@host), which were
logged verbatim at DEBUG level via HikariConfig.logConfiguration().

Add a second pattern that masks the secret following the first colon
of the userinfo, while preserving the username and host:port for log
readability. The query-parameter masking behaviour is unchanged.

Fixes brettwooldridge#2413

Signed-off-by: 付典 <fudianchn@gmail.com>
@fudianchn
fudianchn force-pushed the mask-url-authority-credentials branch from dea2c2c to 6cdeed7 Compare August 15, 2026 15:16
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.

Security: maskPasswordInJdbcUrl does not mask authority-embedded credentials (user:pass@host)

1 participant