Skip to content

Conversation

@rollybueno
Copy link
Contributor

@rollybueno rollybueno commented Oct 15, 2025

Replace addslashes() with str_replace() to avoid over-escaping double quotes in database passwords. Tested using the following complex passwords:
define( 'DB_PASSWORD', 'abcd\"efgh' );
define( 'DB_PASSWORD', 'PasswordWith'SingleQuotes'' );
define( 'DB_PASSWORD', 'p@(ss){w0r?d><}"!With"DoubleQuotes' );

Issue #180

@mrsdizzie
Copy link
Member

This looks mostly good thank you for working on it!

Another side effect of removing addslashes() is that it will not escape the backslash character anymore. This is a bit less obvious to test because it is actually fine in the case of a single backslash in a password. For example, if your password is:

my\password

Then either of these work fine:

define( 'DB_PASSWORD', 'my\\password' );
define( 'DB_PASSWORD', 'my\password' );

In the first case, PHP sees \ which it interprets as an escaped backslash (a single \ at runtime). In the second case, \p is not a recognized escape sequence in single-quoted strings, so both the \ and p are treated as literals, giving the same result. However, if your password has two backslashes in it like:

my\\password

Then the new code doesn't work, because it will insert:

define( 'DB_PASSWORD', 'my\\password' );

When it needs to be this to work properly:

define( 'DB_PASSWORD', 'my\\\\password' );

https://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.single

To specify a literal single quote, escape it with a backslash (). To specify a literal backslash, double it (\). All other instances of backslash will be treated as a literal backslash: this means that the other escape sequences you might be used to, such as \r or \n, will be output literally as specified rather than having any special meaning.

So to keep the existing behavior while avoiding the issue with double-quotes (which addslashes() unnecessarily escapes), I think the change needs to be:

if ( is_string( $value ) ) {
  $value = str_replace( '\\', '\\\\', $value );  // Escape backslashes first
  $value = str_replace( "'", "\\'", $value );    // Then escape single quotes
  return $value;
}

With a test for a password with \\ that gets escaped properly. So probably something like:

When I run `wp config create --skip-check --dbname=somedb --dbuser=someuser --dbpass='my\\password'`
    Then the wp-config.php file should contain:
      """
      define( 'DB_PASSWORD', 'my\\\\password' )
      """

@rollybueno
Copy link
Contributor Author

rollybueno commented Oct 26, 2025

if ( is_string( $value ) ) {
$value = str_replace( '\', '\\', $value ); // Escape backslashes first
$value = str_replace( "'", "\'", $value ); // Then escape single quotes
return $value;
}

This seems working with the following complex passwords as well:
p\@(ss){w0r?d/><}"!Wi\th"Doub\leQuotes = p\\@(ss){w0r?d/><}"!Wi\\th"Doub\\leQuotes
my\password = my\\password
my\password = my\\\\password
p'\'@(ss){w0r?d/><}'!W\ith'Sing\leQuotes = p\'\\\'@(ss){w0r?d/><}\'!W\\ith\'Sing\\leQuotes
p\@(ss){w0r?d/><}"!Wi\th"Doub\leQuotes\"""\\\" = p\\@(ss){w0r?d/><}"!Wi\\th"Doub\\leQuotes\\"""\\\\"

@mrsdizzie
Copy link
Member

Great! Can you add the suggested test for the backslashes as well (Just so we verify it works and then track it going forward)? Then I think this is good.

@swissspidy swissspidy closed this Oct 28, 2025
@swissspidy swissspidy reopened this Oct 28, 2025
@swissspidy
Copy link
Member

^ Just to re-trigger workflows :-)

@codecov
Copy link

codecov bot commented Oct 29, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@mrsdizzie mrsdizzie merged commit f26579b into wp-cli:main Oct 29, 2025
43 checks passed
@mrsdizzie
Copy link
Member

grazie 😊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

"wp config create" generates wrong DB_PASSWORD in wp-config.php when db password has "

3 participants