Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 72f6257

Browse files
authored
fix: escape special characters in postgres password (coder#16510)
Fixes: coder#16319 This PR modifies existing escaping logic for special characters in Postgres password, so it does fail on edge cases like `#` or `$` when parser recognizes as invalid port.
1 parent 700a453 commit 72f6257

File tree

2 files changed

+18
-2
lines changed

2 files changed

+18
-2
lines changed

cli/server.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -2565,6 +2565,8 @@ func parseExternalAuthProvidersFromEnv(prefix string, environ []string) ([]coder
25652565
return providers, nil
25662566
}
25672567

2568+
var reInvalidPortAfterHost = regexp.MustCompile(`invalid port ".+" after host`)
2569+
25682570
// If the user provides a postgres URL with a password that contains special
25692571
// characters, the URL will be invalid. We need to escape the password so that
25702572
// the URL parse doesn't fail at the DB connector level.
@@ -2573,7 +2575,11 @@ func escapePostgresURLUserInfo(v string) (string, error) {
25732575
// I wish I could use errors.Is here, but this error is not declared as a
25742576
// variable in net/url. :(
25752577
if err != nil {
2576-
if strings.Contains(err.Error(), "net/url: invalid userinfo") {
2578+
// Warning: The parser may also fail with an "invalid port" error if the password contains special
2579+
// characters. It does not detect invalid user information but instead incorrectly reports an invalid port.
2580+
//
2581+
// See: https://github.com/coder/coder/issues/16319
2582+
if strings.Contains(err.Error(), "net/url: invalid userinfo") || reInvalidPortAfterHost.MatchString(err.Error()) {
25772583
// If the URL is invalid, we assume it is because the password contains
25782584
// special characters that need to be escaped.
25792585

cli/server_internal_test.go

+11-1
Original file line numberDiff line numberDiff line change
@@ -351,13 +351,23 @@ func TestEscapePostgresURLUserInfo(t *testing.T) {
351351
output: "",
352352
err: xerrors.New("parse postgres url: parse \"postgres://local host:5432/coder\": invalid character \" \" in host name"),
353353
},
354+
{
355+
input: "postgres://coder:co?der@localhost:5432/coder",
356+
output: "postgres://coder:co%3Fder@localhost:5432/coder",
357+
err: nil,
358+
},
359+
{
360+
input: "postgres://coder:co#der@localhost:5432/coder",
361+
output: "postgres://coder:co%23der@localhost:5432/coder",
362+
err: nil,
363+
},
354364
}
355365
for _, tc := range testcases {
356366
tc := tc
357367
t.Run(tc.input, func(t *testing.T) {
358368
t.Parallel()
359369
o, err := escapePostgresURLUserInfo(tc.input)
360-
require.Equal(t, tc.output, o)
370+
assert.Equal(t, tc.output, o)
361371
if tc.err != nil {
362372
require.Error(t, err)
363373
require.EqualValues(t, tc.err.Error(), err.Error())

0 commit comments

Comments
 (0)