From 0d55e175c7d043008e0dc22faf32f39141a2a574 Mon Sep 17 00:00:00 2001 From: Tim Smith Date: Sat, 6 Jun 2026 09:23:57 -0700 Subject: [PATCH] URL-encode credentials in PostgreSQL connection URI make_connection_string interpolated the database username and password directly into a libpq connection URI: "postgresql:///#{db_name}?user=#{db_user}&password=#{db_password}&host=#{host}&port=#{port}" Neither value was URL-encoded. A username or password containing characters that are significant in a connection URI (such as '&', '?', '#', '/', or spaces) would break the URI or inject additional connection parameters (for example appending '&sslmode=disable'). The DB superuser password can be set to an arbitrary value via set-db-superuser-password, so this is reachable with non-random credentials. URL-encode the username and password with ERB::Util.url_encode before building the URI. Plain alphanumeric credentials are unaffected. Signed-off-by: Tim Smith --- src/chef-server-ctl/lib/chef_server_ctl/config.rb | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/chef-server-ctl/lib/chef_server_ctl/config.rb b/src/chef-server-ctl/lib/chef_server_ctl/config.rb index 1281331d4c..1c01319d79 100644 --- a/src/chef-server-ctl/lib/chef_server_ctl/config.rb +++ b/src/chef-server-ctl/lib/chef_server_ctl/config.rb @@ -1,5 +1,6 @@ require "chef_server_ctl/log" require "chef-utils/dist" +require "erb" # ChefServerCtl::Config is a global configuration class for # ChefServerCtl subcommands. @@ -148,7 +149,15 @@ def self.make_connection_string(db_name, db_user, db_password) pg_config = @@ctl.running_service_config("postgresql") host = pg_config["vip"] port = pg_config["port"] - "postgresql:///#{db_name}?user=#{db_user}&password=#{db_password}&host=#{host}&port=#{port}" + # URL-encode the credentials. A username or password containing + # characters that are significant in a libpq connection URI (such as + # '&', '?', '#', '/', or spaces) would otherwise break the URI or + # inject additional connection parameters. The DB superuser password, + # for example, can be set to an arbitrary value via + # set-db-superuser-password. + user = ERB::Util.url_encode(db_user.to_s) + password = ERB::Util.url_encode(db_password.to_s) + "postgresql:///#{db_name}?user=#{user}&password=#{password}&host=#{host}&port=#{port}" end def self.ssl_params