Repository navigation
fix(legacy): use SSL_CERT_FILE on Windows, as Go does - #260
Conversation
Since #259, the embedded PHP on Windows verifies certificates with Schannel against the Windows certificate store, and ignored SSL_CERT_FILE. Go (since 1.27) still uses it on Windows, so with it set, Go and PHP commands would trust different certificates, as before #141. The wrapper now passes SSL_CERT_FILE to PHP as openssl.cafile, which PHP gives to every curl handle as CURLOPT_CAINFO. Schannel then verifies against that file instead of the store, as v5.15.0 did (through Composer\CaBundle) and as Go does. Without SSL_CERT_FILE, nothing is passed and the store is used. An unusable file makes requests fail, as in Go. SSL_CERT_DIR is still not supported on Windows, as Schannel cannot use a directory. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The wrapper now sets openssl.cafile to "${SSL_CERT_FILE}", which PHP
expands itself, instead of quoting and escaping the path. A path with a
literal "${...}" was otherwise expanded by PHP's ini parser. The ini
escaping helper is removed, and the test checks paths with "~",
backslashes, "$" and quotes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Warning
Changes suggested — 🟡 1 warning
🔍 Full review · 8 files reviewed
Verification
settings()returns nil whenSSL_CERT_FILEis empty or unset, and Go's crypto/x509 also ignores an empty value, so the two agree there.makeCmdputs the-dsettings after-nand before the phar path, so PHP applies them as INI entries rather than handing them to the CLI as arguments.Execcopiesos.Environ()into the child's environment, so${SSL_CERT_FILE}is defined when PHP expands the INI value.- The new Windows tests reuse
generateTestCA,phpRequestScriptand the curl error constants fromcert_store_windows_test.go, which builds only on Windows like they do.
The new TestWindowsSSLCertFileSetting and TestWindowsSSLCertFile match -run TestWindows, so CI's windows-cert-store job in ci.yml runs them. They call PHP directly with settings() rather than through makeCmd/Exec, and no test covers HTTPS-proxy verification.
Review details
- Commit: 5b06fbc
- Model: claude-opus-5-5
Review 1 of 10 for this pull request · View the full run
PHP passes openssl.cafile to curl as CURLOPT_CAINFO, which only covers servers: curl verifies an HTTPS proxy with CURLOPT_PROXY_CAINFO, without falling back to CAINFO. So with SSL_CERT_FILE set, Schannel still verified a proxy against the Windows store, while Go uses the file for both. With Schannel, getGuzzleOptions() now also sets CURLOPT_PROXY_CAINFO from openssl.cafile when it is set. The Windows test checks both cases through an HTTPS proxy. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
📋 PR Summary On Windows, the wrapper now starts the embedded PHP with Changes
|
Since #259, the embedded PHP on Windows ignores
SSL_CERT_FILE, while Go (since 1.27) still uses it on Windows. With it set, Go and PHP commands would trust different certificates, which #141 fixed before.The wrapper now starts PHP on Windows with
-d openssl.cafile="${SSL_CERT_FILE}"when the variable is set. PHP expands the variable itself, so the path needs no escaping. PHP givesopenssl.cafileto every curl handle asCURLOPT_CAINFO, and Schannel then verifies against that file instead of the Windows certificate store, as v5.15.0 did (throughComposer\CaBundle) and as Go does. Without the variable, nothing is passed and the store is used, as in #259. An unusable file makes requests fail, as in Go.PHP only passes
openssl.cafileto curl for servers (CURLOPT_CAINFO), and curl verifies an HTTPS proxy withCURLOPT_PROXY_CAINFO, without falling back. So with Schannel,Config::getGuzzleOptions()also setsCURLOPT_PROXY_CAINFOfromopenssl.cafilewhen it is set, as Go uses the file for both.SSL_CERT_DIRis still not supported on Windows, as Schannel can't use a directory.Tests (Windows only, run in CI's
windows-cert-storejob, no administrator rights needed):TestWindowsSSLCertFileSetting: PHP reads paths with~, backslashes, a UNC prefix,${...},$and quotes back unchanged.TestWindowsSSLCertFile: a request through PHP's curl with the wrapper's settings succeeds with a file holding the server's root, and fails with one without it (error 60) or a missing file (error 77). It fails without this change. Through an HTTPS proxy, the proxy is only verified with the file whenCURLOPT_PROXY_CAINFOis set.Also checked on Windows 11 with a build of this branch, using a fake API token: the token request to the auth server gets an authentication error (so TLS succeeded) with no
SSL_CERT_FILEand with the curl.se bundle, and a Schannel untrusted-root error with a file without the right roots. Through a local HTTPS proxy with its own CA, the request succeeds when the proxy's CA is inSSL_CERT_FILE(it failed before the last commit), and fails when it is not, or whenSSL_CERT_FILEis unset.🤖 Generated with Claude Code