[wp-trac] [WordPress Trac] #63876: Certificate verification failure causing PHP 8.3 and 8.4 workflows to fail

WordPress Trac noreply at wordpress.org
Wed Sep 3 03:01:44 UTC 2025


#63876: Certificate verification failure causing PHP 8.3 and 8.4 workflows to fail
------------------------------+------------------------------
 Reporter:  johnbillion       |       Owner:  (none)
     Type:  defect (bug)      |      Status:  new
 Priority:  normal            |   Milestone:  Awaiting Review
Component:  Build/Test Tools  |     Version:
 Severity:  normal            |  Resolution:
 Keywords:  has-patch         |     Focuses:
------------------------------+------------------------------

Comment (by desrosj):

 I wanted to document some debugging findings with the help of ChatGPT. For
 everything below, I had [60659] checked out (the last commit prior to the
 temporary band-aid introduced in [60660]), `8.3-fpm` as the value for
 `LOCAL_PHP` in my `.env` file, the default MySQL 8.4 version, and
 xDebug/Memcached disabled.

 I started with these commands.
 {{{
 # From host:
 docker compose exec cli bash

 # Try a strict TLS connection using the same host as the local environment
 mysql -h mysql -u root -p"$MYSQL_ROOT_PASSWORD" \
   --ssl-mode=VERIFY_IDENTITY \
   --ssl-ca=/etc/ssl/certs/ca-certificates.crt \
   -e 'SELECT VERSION(), @@sql_mode;'
 }}}

 This gave me an error: `mysql: unknown variable 'ssl-
 mode=VERIFY_IDENTITY'`. According to ChatGPT:

 > That error means your CLI is the MariaDB client, not Oracle’s MySQL
 client. MariaDB’s `mysql` does not support `--ssl-mode=VERIFY_IDENTITY`,
 so it treats it like a bogus “variable” and fails.

 Interesting. Running `mysql --version` confirmed this: `mysql from
 11.8.2-MariaDB, client 15.2 for debian-linux-gnu (x86_64) using  EditLine
 wrapper`

 The previous command to test the TLS connection needs to be changed a bit:

 {{{
 mysql -h mysql -u root -p"$MYSQL_ROOT_PASSWORD" \
   --ssl \
   --ssl-ca=/etc/ssl/certs/ca-certificates.crt \
   --ssl-verify-server-cert \
   -e 'SHOW STATUS LIKE "Ssl_cipher"; SELECT VERSION(), @@sql_mode;'
 }}}

 This outputs a similar error to the one in the description: `ERROR 2026
 (HY000): TLS/SSL error: self-signed certificate in certificate chain`.

 Next, I ran some commands to figure out what the `mysql` container is
 serving for a certificate:

 {{{
 # Fetch the chain and let OpenSSL verify against the system bundle
 openssl s_client -connect mysql:3306 -starttls mysql -servername mysql
 -showcerts \
   -CAfile /etc/ssl/certs/ca-certificates.crt </dev/null 2>/dev/null | \
   awk '/^subject=|^issuer=|^Verify return code|BEGIN CERTIFICATE|END
 CERTIFICATE/ {print}'

 # Also show negotiated cipher to confirm you reached TLS
 openssl s_client -connect mysql:3306 -starttls mysql -servername mysql
 </dev/null 2>/dev/null | \
   awk '/Protocol|Cipher/ {print}'

 }}}

 This outputs the following:

 {{{
 -----BEGIN CERTIFICATE-----
 -----END CERTIFICATE-----
 -----BEGIN CERTIFICATE-----
 -----END CERTIFICATE-----
 subject=CN=MySQL_Server_8.4.6_Auto_Generated_Server_Certificate
 issuer=CN=MySQL_Server_8.4.6_Auto_Generated_CA_Certificate
 Verify return code: 19 (self-signed certificate in certificate chain)

 New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
 Protocol: TLSv1.3
     Protocol  : TLSv1.3
     Cipher    : TLS_AES_256_GCM_SHA384
     Protocol  : TLSv1.3
     Cipher    : TLS_AES_256_GCM_SHA384
 }}}

 Switching over to the `mysql` container using `docker compose exec mysql
 bash`, I next ran this: `mysql -u root -p"$MYSQL_ROOT_PASSWORD" -e "SHOW
 VARIABLES LIKE 'ssl%'; SHOW STATUS LIKE 'Ssl_%';"`

 This output the following:
 {{{
 +---------------------------+-----------------+
 | Variable_name             | Value           |
 +---------------------------+-----------------+
 | ssl_ca                    | ca.pem          |
 | ssl_capath                |                 |
 | ssl_cert                  | server-cert.pem |
 | ssl_cipher                |                 |
 | ssl_crl                   |                 |
 | ssl_crlpath               |                 |
 | ssl_fips_mode             | OFF             |
 | ssl_key                   | server-key.pem  |
 | ssl_session_cache_mode    | ON              |
 | ssl_session_cache_timeout | 300             |
 +---------------------------+-----------------+
 +--------------------------------+--------------------------+
 | Variable_name                  | Value                    |
 +--------------------------------+--------------------------+
 | Ssl_accept_renegotiates        | 0                        |
 | Ssl_accepts                    | 11                       |
 | Ssl_callback_cache_hits        | 0                        |
 | Ssl_cipher                     |                          |
 | Ssl_cipher_list                |                          |
 | Ssl_client_connects            | 0                        |
 | Ssl_connect_renegotiates       | 0                        |
 | Ssl_ctx_verify_depth           | 18446744073709551615     |
 | Ssl_ctx_verify_mode            | 5                        |
 | Ssl_default_timeout            | 0                        |
 | Ssl_finished_accepts           | 10                       |
 | Ssl_finished_connects          | 0                        |
 | Ssl_server_not_after           | Aug 31 17:48:40 2035 GMT |
 | Ssl_server_not_before          | Sep  2 17:48:40 2025 GMT |
 | Ssl_session_cache_hits         | 0                        |
 | Ssl_session_cache_misses       | 0                        |
 | Ssl_session_cache_mode         | SERVER                   |
 | Ssl_session_cache_overflows    | 0                        |
 | Ssl_session_cache_size         | 128                      |
 | Ssl_session_cache_timeout      | 300                      |
 | Ssl_session_cache_timeouts     | 0                        |
 | Ssl_sessions_reused            | 0                        |
 | Ssl_used_session_cache_entries | 0                        |
 | Ssl_verify_depth               | 0                        |
 | Ssl_verify_mode                | 0                        |
 | Ssl_version                    |                          |
 +--------------------------------+--------------------------+
 }}}
 `CN=MySQL_Server_8.4.6_Auto_Generated_Server_Certificate/CN=MySQL_Server_8.4.6_Auto_Generated_CA_Certificate`
 confirms that the database container is using the auto-generated
 certificate issued by a private, untrusted certificate authority at the
 time and date I first ran `npm run env:start`.

 I've tried several ways to get the PHP/CLI containers to recognize and
 trust this custom certificate authority, but haven't had any luck. I'll
 follow up with documenting that next time I have a chance.

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/63876#comment:6>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list