[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