Skip to content

URL-encode credentials in PostgreSQL connection URI#4206

Open
tas50 wants to merge 1 commit into
chef:mainfrom
tas50:fix-csc-pg-conn-uri-encoding
Open

URL-encode credentials in PostgreSQL connection URI#4206
tas50 wants to merge 1 commit into
chef:mainfrom
tas50:fix-csc-pg-conn-uri-encoding

Conversation

@tas50

@tas50 tas50 commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Problem

ChefServerCtl::Config.make_connection_string in src/chef-server-ctl/lib/chef_server_ctl/config.rb interpolates the database username and password directly into a libpq connection URI without URL-encoding:

"postgresql:///#{db_name}?user=#{db_user}&password=#{db_password}&host=#{host}&port=#{port}"

If a username or password contains characters that are significant in a connection URI — &, ?, #, /, or spaces — the resulting URI is either malformed or carries extra connection parameters that the credential value injects. For example a password value of secret&sslmode=disable would append an unintended sslmode parameter to the connection.

The DB superuser password is not limited to randomly generated values — it can be set to an arbitrary string via chef-server-ctl set-db-superuser-password — so this is reachable in practice, not just in theory.

Fix

URL-encode the username and password with ERB::Util.url_encode before building the URI:

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}"

Plain alphanumeric credentials are unchanged; only URI-significant characters are percent-encoded, which libpq decodes back to the original value. (ERB::Util.url_encode encodes spaces as %20 rather than +, which is what a libpq URI expects.)

Note: the chef-server-ctl gem bundle targets Ruby 3.1 and could not be installed in my local environment (Ruby 4.x), so I verified the change with ruby -c and confirmed the encoding behavior of ERB::Util.url_encode directly.

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 <tsmith84@proton.me>
@tas50 tas50 requested review from a team as code owners June 6, 2026 16:24
@netlify

netlify Bot commented Jun 6, 2026

Copy link
Copy Markdown

👷 Deploy Preview for chef-server processing.

Name Link
🔨 Latest commit 0d55e17
🔍 Latest deploy log https://app.netlify.com/projects/chef-server/deploys/6a2449ae69c6ab0008c43d9f

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.

1 participant