mirror of
https://github.com/coder/coder.git
synced 2025-07-12 00:14:10 +00:00
fix: escape special characters in postgres password (#16510)
Fixes: https://github.com/coder/coder/issues/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.
This commit is contained in:
@ -2565,6 +2565,8 @@ func parseExternalAuthProvidersFromEnv(prefix string, environ []string) ([]coder
|
|||||||
return providers, nil
|
return providers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var reInvalidPortAfterHost = regexp.MustCompile(`invalid port ".+" after host`)
|
||||||
|
|
||||||
// If the user provides a postgres URL with a password that contains special
|
// If the user provides a postgres URL with a password that contains special
|
||||||
// characters, the URL will be invalid. We need to escape the password so that
|
// characters, the URL will be invalid. We need to escape the password so that
|
||||||
// the URL parse doesn't fail at the DB connector level.
|
// the URL parse doesn't fail at the DB connector level.
|
||||||
@ -2573,7 +2575,11 @@ func escapePostgresURLUserInfo(v string) (string, error) {
|
|||||||
// I wish I could use errors.Is here, but this error is not declared as a
|
// I wish I could use errors.Is here, but this error is not declared as a
|
||||||
// variable in net/url. :(
|
// variable in net/url. :(
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if strings.Contains(err.Error(), "net/url: invalid userinfo") {
|
// Warning: The parser may also fail with an "invalid port" error if the password contains special
|
||||||
|
// characters. It does not detect invalid user information but instead incorrectly reports an invalid port.
|
||||||
|
//
|
||||||
|
// See: https://github.com/coder/coder/issues/16319
|
||||||
|
if strings.Contains(err.Error(), "net/url: invalid userinfo") || reInvalidPortAfterHost.MatchString(err.Error()) {
|
||||||
// If the URL is invalid, we assume it is because the password contains
|
// If the URL is invalid, we assume it is because the password contains
|
||||||
// special characters that need to be escaped.
|
// special characters that need to be escaped.
|
||||||
|
|
||||||
|
@ -351,13 +351,23 @@ func TestEscapePostgresURLUserInfo(t *testing.T) {
|
|||||||
output: "",
|
output: "",
|
||||||
err: xerrors.New("parse postgres url: parse \"postgres://local host:5432/coder\": invalid character \" \" in host name"),
|
err: xerrors.New("parse postgres url: parse \"postgres://local host:5432/coder\": invalid character \" \" in host name"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
input: "postgres://coder:co?der@localhost:5432/coder",
|
||||||
|
output: "postgres://coder:co%3Fder@localhost:5432/coder",
|
||||||
|
err: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "postgres://coder:co#der@localhost:5432/coder",
|
||||||
|
output: "postgres://coder:co%23der@localhost:5432/coder",
|
||||||
|
err: nil,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range testcases {
|
for _, tc := range testcases {
|
||||||
tc := tc
|
tc := tc
|
||||||
t.Run(tc.input, func(t *testing.T) {
|
t.Run(tc.input, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
o, err := escapePostgresURLUserInfo(tc.input)
|
o, err := escapePostgresURLUserInfo(tc.input)
|
||||||
require.Equal(t, tc.output, o)
|
assert.Equal(t, tc.output, o)
|
||||||
if tc.err != nil {
|
if tc.err != nil {
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
require.EqualValues(t, tc.err.Error(), err.Error())
|
require.EqualValues(t, tc.err.Error(), err.Error())
|
||||||
|
Reference in New Issue
Block a user