fix: URL-encode and shell-escape sqlx migration DSN#2175
Conversation
The migration DSN in src/inc/startup/setup.php was built by string concatenation and passed unquoted, non-URL-encoded into exec(). Database passwords/usernames containing URL-special (@ : / # ? [ ]) or shell-special ($ & ; | space etc.) characters corrupted the DSN and broke server startup. rawurlencode() the userinfo and escapeshellarg() the exec arguments. Affects both the mysql and postgres DSNs.
Standalone reproduction + fix verificationSince standing up the full stack is heavy, here is a self-contained PHP script that proves both halves of the bug and the fix, using a password with the exact problem characters: Before: raw concatenation produces a DSN that After: |
Problem
In
src/inc/startup/setup.phpthe sqlx migration DSN is built by string concatenation and passed unquoted and non-URL-encoded straight intoexec('/usr/bin/sqlx migrate run ... -D ' . $database_uri).This breaks server startup whenever the database username or password contains:
@ : / # ? [ ]) — they corrupt the DSN thatsqlxparses (e.g. an@in the password is read as the userinfo/host separator).$ & ; | < > ( ) *, space, backtick, etc.) —sh -cinterprets them beforesqlxever runs (e.g.&backgrounds the truncated command and splits the DSN).Hit in production with an auto-generated DB password containing
$and&:This affects both the mysql and postgres DSNs (same construction).
Fix
Two small, independent hardening changes:
rawurlencode()the userinfo (username + password) components of the DSN so URL-special characters survive parsing.escapeshellarg()the arguments passed toexec()(the migrations--sourcepath and the-DDSN) so shell-special characters are passed literally.No behavioral change for credentials that contain only safe characters.
Fixes #2174