diff --git a/mysql/mysql.go b/mysql/mysql.go index 4cd1e2e4b1..0028f26ef3 100644 --- a/mysql/mysql.go +++ b/mysql/mysql.go @@ -79,7 +79,13 @@ func ConfigFromURL(u *url.URL) (cfg *mysql.Config, err error) { cfg.Passwd, _ = u.User.Password() cfg.DBName = dbName if _, ok := u.Query()["allowCleartextPasswords"]; !ok { - cfg.AllowCleartextPasswords = true + // The cleartext auth plugin hands the password to whatever answers on + // the database address, so it is only safe once the server's identity + // has been verified. Enable it by default only when the connection is + // TLS-protected with certificate verification and no plaintext + // fallback; otherwise applications must opt in explicitly with + // "allowCleartextPasswords=true". + cfg.AllowCleartextPasswords = cfg.TLS != nil && !cfg.TLS.InsecureSkipVerify && !cfg.AllowFallbackToPlaintext } cfg.AllowNativePasswords = true return cfg, nil diff --git a/mysql/mysql_test.go b/mysql/mysql_test.go index 71bb7f8427..215d94b868 100644 --- a/mysql/mysql_test.go +++ b/mysql/mysql_test.go @@ -99,10 +99,30 @@ func TestConfigFromURLCleartextPasswords(t *testing.T) { want bool }{ { - name: "default", + name: "default, no TLS", url: "mysql://user:password@localhost/db", + want: false, + }, + { + name: "default, no TLS, other query params present", + url: "mysql://user:password@localhost/db?timeout=5s", + want: false, + }, + { + name: "default, TLS with verification", + url: "mysql://user:password@localhost/db?tls=true", want: true, }, + { + name: "default, TLS without verification", + url: "mysql://user:password@localhost/db?tls=skip-verify", + want: false, + }, + { + name: "default, TLS with plaintext fallback", + url: "mysql://user:password@localhost/db?tls=preferred", + want: false, + }, { name: "explicit false", url: "mysql://user:password@localhost/db?allowCleartextPasswords=false", @@ -113,6 +133,11 @@ func TestConfigFromURLCleartextPasswords(t *testing.T) { url: "mysql://user:password@localhost/db?allowCleartextPasswords=true", want: true, }, + { + name: "explicit true without TLS", + url: "mysql://user:password@localhost/db?allowCleartextPasswords=true&tls=false", + want: true, + }, } { t.Run(tc.name, func(t *testing.T) { u, err := url.Parse(tc.url)