Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions features/db-query.feature
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,21 @@ Feature: Query the database with WordPress' MySQL config
"""
ANSI
"""

# Regression test for https://github.com/wp-cli/db-command/issues/309
# MariaDB 11.4+ verifies the server certificate by default and prints a warning to
# STDERR (or fails) against the auto-generated self-signed certificate, which broke
# the tests. `run()` now opts out via `--skip-ssl-verify-server-cert` on MariaDB, and
# both `ssl-verify-server-cert` and its `skip-` variant are allowed so the behaviour
# can be overridden. Assert the flag is forwarded to the MySQL client (visible in the
# debug output before the connection is attempted). SQLite does not use the MySQL
# client, hence the tag.
@require-mysql-or-mariadb
Scenario: Query forwards the ssl-verify-server-cert flags to the MySQL client
Given a WP install

When I try `wp db query "SELECT 1" --skip-ssl-verify-server-cert --debug`
Then STDERR should contain:
"""
skip-ssl-verify-server-cert
"""
Comment on lines +135 to +139

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
printf '\n## features/db-query.feature (around lines 120-150)\n'
sed -n '120,150p' features/db-query.feature | cat -n
printf '\n## src/DB_Command.php around query and mysql args\n'
rg -n "function query|get_mysql_args|skip-ssl-verify-server-cert|run\(" src/DB_Command.php
sed -n '560,700p' src/DB_Command.php | cat -n

Repository: wp-cli/db-command

Length of output: 8621


🏁 Script executed:

#!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
path = Path('src/DB_Command.php')
lines = path.read_text().splitlines()
for start,end in [(600,690)]:
    print(f"\n## {path} lines {start}-{end}")
    for i in range(start-1, min(end, len(lines))):
        print(f"{i+1:4d}: {lines[i]}")
PY
printf '\n## search for debug/logging related to assoc args or command printing\n'
rg -n "assoc_args|debug|STDERR|run\(|mysql args|get_mysql_args|skip-ssl-verify-server-cert" src/DB_Command.php src -g '!vendor'

Repository: wp-cli/db-command

Length of output: 38664


🌐 Web query:

WP-CLI DB_Command skip-ssl-verify-server-cert query assoc_args self::run get_mysql_args debug STDERR

💡 Result:

In WP-CLI's DB_Command implementation, the ssl-verify-server-cert flag and its associated handling are primarily used to manage SSL/TLS connection requirements and suppress specific warnings during database operations, particularly when using MariaDB [1][2]. Key details regarding the components you mentioned: 1. ssl-verify-server-cert: This flag is included in WP-CLI's internal allow-list for MySQL/MariaDB connection arguments [1][3]. When using MariaDB, WP-CLI may automatically inject --ssl-verify-server-cert into the database command to prevent "insecure passwordless login" warnings from cluttering STDERR during automated processes like Behat tests [1][2]. 2. get_mysql_args(): This method in DB_Command is responsible for filtering user-provided arguments against an allow-list of valid MySQL client options [4]. It ensures that flags like ssl-verify-server-cert, ssl, and skip-ssl are correctly passed to the underlying MySQL or MariaDB client binary [4]. 3. self::run() and debug: WP-CLI executes database commands by constructing a shell command and invoking it via self::run() [5][6]. When the --debug global flag is used, WP-CLI outputs the final, constructed MySQL command string and the associative arguments being passed, which is useful for verifying that flags like --ssl-verify-server-cert are being correctly applied [7][6][4]. 4. STDERR: In many environments, especially with MariaDB, SSL warnings are output to STDERR [1][2]. If these warnings occur during SQL mode discovery or connection establishment, they can sometimes cause WP-CLI commands to fail or produce unexpected output [7][2]. Technical Context and Known Issues: The handling of SSL and default configurations has been a point of development within WP-CLI [8][3]. Specifically, WP-CLI often uses a --no-defaults flag by default to avoid issues with misconfigured local environments, but this can prevent the MySQL client from respecting SSL configuration files [9][10][2]. Users encountering SSL connection failures (e.g., certificate verification errors) often need to use the --defaults flag or explicitly pass additional SSL-related arguments [9][3][10]. Recent PRs have focused on improving how wp db commands handle these arguments to ensure better compatibility with modern SSL/TLS-secured database environments [3][4].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path

path = Path('src/DB_Command.php')
lines = path.read_text().splitlines()

for start, end, title in [
    (1969, 2025, 'run()'),
    (2176, 2290, 'get_mysql_args()'),
]:
    print(f"\n## {title} ({path} lines {start}-{end})")
    for i in range(start - 1, min(end, len(lines))):
        print(f"{i+1:4d}: {lines[i]}")
PY

Repository: wp-cli/db-command

Length of output: 5999


Assert the spawned mysql argv
features/db-query.feature:16-19--debug can print the parsed assoc args before self::run(), so this check can pass without proving the option reached the MySQL client. Assert the final client arguments instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@features/db-query.feature` around lines 135 - 139, Update the scenario around
the `--skip-ssl-verify-server-cert` assertion to verify the spawned MySQL
client’s final argv rather than relying on `--debug` output from parsed
arguments. Reuse the existing test mechanism for inspecting client arguments and
assert that the SSL-skip option is present in the arguments passed to MySQL.

13 changes: 13 additions & 0 deletions src/DB_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -1988,6 +1988,17 @@ private static function run( $cmd, $assoc_args = [], $send_to_shell = true, $int
unset( $assoc_args['dbpass'], $assoc_args['password'] );
}

// MariaDB 11.4 enables TLS server certificate verification by default. WP-CLI
// connects the same way WordPress does, which does not verify the certificate,
// and against MariaDB's auto-generated self-signed certificate verification
// either just warns on STDERR that it disabled itself or fails outright. Opt out
// explicitly to keep the previous behaviour, unless the user asked to verify.
if ( 'mariadb' === Utils\get_db_type()
&& ! isset( $assoc_args['ssl-verify-server-cert'] )
&& ! isset( $assoc_args['skip-ssl-verify-server-cert'] ) ) {
$required['skip-ssl-verify-server-cert'] = true;
}
Comment on lines +1991 to +2000

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

sed -n '1960,2025p;835,860p;2360,2400p' src/DB_Command.php

Repository: wp-cli/db-command

Length of output: 4415


🏁 Script executed:

python3 - <<'PY'
from pathlib import Path
p = Path('src/DB_Command.php')
text = p.read_text()
for start,end in [(1960,2025),(835,860),(2360,2400)]:
    print(f'--- {start}-{end} ---')
    for i,line in enumerate(text.splitlines(),1):
        if start <= i <= end:
            print(f'{i}:{line}')
PY

Repository: wp-cli/db-command

Length of output: 5106


🏁 Script executed:

rg -n "ssl-verify-server-cert|skip-ssl-verify-server-cert|get_current_sql_modes|get_posts_table_charset|function run\(" src/DB_Command.php

Repository: wp-cli/db-command

Length of output: 859


🌐 Web query:

"src/DB_Command.php get_current_sql_modes get_posts_table_charset WP-CLI MariaDB skip-ssl-verify-server-cert"

💡 Result:

The components you identified are part of the wp-cli/db-command package, which manages database interactions for WP-CLI [1][2][3]. get_current_sql_modes This is a internal function used by WP-CLI to retrieve the active SQL modes of the MySQL/MariaDB session (via SELECT @@SESSION.sql_mode) to ensure compatibility with WordPress database operations [4][5]. It has been a source of various issues, particularly when connecting to databases using SSL/TLS, as the command internally forces specific flags (like --no-defaults) that may override necessary user configurations [1][4][6]. get_posts_table_charset This typically refers to logic or methods used to identify the character set of the WordPress posts table [2]. It is important for ensuring proper data handling and query execution, and fixes have been implemented in the past to correctly handle how these character sets are retrieved and processed to avoid command failures [2]. skip-ssl-verify-server-cert This relates to handling SSL/TLS certificate verification in MariaDB and MySQL connections [7]. Recent MariaDB versions (11.4+) enable SSL and --ssl-verify-server-cert by default [6][8]. This has caused significant friction in WP-CLI environments, leading to warnings or errors (such as TLS certificate verification failures or passwordless login warnings) [1][9][7][10]. To address this, updates have been made to the WP-CLI db-command package to: - Conditionally add --ssl-verify-server-cert for MariaDB connections to suppress insecure login warnings [7]. - Add ssl-verify-server-cert to the list of allowed MySQL options [3][7]. - Attempt to better preserve user-supplied connection arguments (like --defaults) which were previously stripped by the tool's internal commands, causing connection failures [3][6]. If you are encountering issues, ensure you are using a recent version of the wp-cli/db-command package, as these connection-related bugs are actively being addressed [3][7].

Citations:


🏁 Script executed:

sed -n '900,1040p;1180,1260p;2200,2265p' src/DB_Command.php

Repository: wp-cli/db-command

Length of output: 8498


🏁 Script executed:

rg -n "function get_defaults_flag_string|get_defaults_flag_string\(" src/DB_Command.php

Repository: wp-cli/db-command

Length of output: 828


🏁 Script executed:

sed -n '520,700p;1040,1185p;2200,2265p' src/DB_Command.php

Repository: wp-cli/db-command

Length of output: 13003


🏁 Script executed:

python3 - <<'PY'
from pathlib import Path
text = Path('src/DB_Command.php').read_text().splitlines()
for start,end in [(520,700),(1040,1185),(2200,2265)]:
    print(f'--- {start}-{end} ---')
    for i,line in enumerate(text,1):
        if start <= i <= end:
            print(f'{i}:{line}')
PY

Repository: wp-cli/db-command

Length of output: 14839


🏁 Script executed:

rg -n "function get_defaults_flag_string|get_defaults_flag_string\(" src/DB_Command.php && sed -n '1260,1385p' src/DB_Command.php

Repository: wp-cli/db-command

Length of output: 3946


🏁 Script executed:

sed -n '2280,2335p' src/DB_Command.php

Repository: wp-cli/db-command

Length of output: 1842


🏁 Script executed:

python3 - <<'PY'
from pathlib import Path
text = Path('src/DB_Command.php').read_text().splitlines()
for start,end in [(2280,2335)]:
    print(f'--- {start}-{end} ---')
    for i,line in enumerate(text,1):
        if start <= i <= end:
            print(f'{i}:{line}')
PY

Repository: wp-cli/db-command

Length of output: 2140


Forward SSL flags into internal DB queries.
get_current_sql_modes() and get_posts_table_charset() build the command string with $assoc_args but pass only execute into self::run(), so an explicit --ssl-verify-server-cert is still dropped and MariaDB re-injects skip-ssl-verify-server-cert for those helper connections. Pass the caller’s SSL-related args through.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/DB_Command.php` around lines 1991 - 2000, The helper queries
get_current_sql_modes() and get_posts_table_charset() currently pass only
execute to self::run(), dropping explicit SSL verification flags. Forward the
caller’s SSL-related entries from $assoc_args when invoking self::run() so both
helper connections preserve --ssl-verify-server-cert and
--skip-ssl-verify-server-cert choices.


$final_args = array_merge( $required, $assoc_args );

// Filter out empty string values to avoid passing empty parameters to MySQL commands
Expand Down Expand Up @@ -2232,6 +2243,7 @@ private static function get_mysql_args( $assoc_args ) {
'skip-pager',
'skip-reconnect',
'skip-ssl',
'skip-ssl-verify-server-cert',
'socket',
'ssl',
'ssl-ca',
Expand All @@ -2243,6 +2255,7 @@ private static function get_mysql_args( $assoc_args ) {
'ssl-fips-mode',
'ssl-key',
'ssl-mode',
'ssl-verify-server-cert',
'syslog',
'table',
'tee',
Expand Down
Loading