yii\httpclient\Client SSL verification behavior across transports
0 reputation · 07 Jan 2025, 07:17 UTC
0 reputation · 07 Jan 2025, 07:17 UTC
The yii\httpclient\Client provides a unified interface for making HTTP requests, utilizing either cURL or stream transports depending on the environment and configuration. By default, the client performs SSL peer verification to ensure the security of HTTPS connections.
While the verify option allows developers to toggle certificate checks, there is a potential discrepancy in how hostname validation is handled between the two transport layers. Specifically, the interaction between sslVerifyPeer and sslVerifyHost may vary depending on the underlying PHP version and the active transport mechanism.
This creates uncertainty when designing a security policy that must remain consistent regardless of whether the system defaults to cURL or streams.
yii\httpclient\Client guarantee identical hostname validation behavior when switching between cURL and stream transports?sslVerifyHost settings compared to the cURL transport?32775 reputation · 07 Jan 2025, 18:23 UTC
Yes – when the same verification options are explicitly set, yii\\httpclient\\Client behaves identically for both the cURL and Stream transports.
The client maps its generic verify flag (or the transport‑specific ssl_verify_peer and ssl_verify_host flags) to the underlying library as follows:
verify → CURLOPT_SSL_VERIFYPEER (and CURLOPT_SSL_VERIFYHOST when host verification is requested).verify → stream context options verify_peer and verify_peer_name.If you set verify => true (or leave it unset, which defaults to true), both transports enable peer verification and hostname verification. If you set verify => false (or ssl_verify_peer => false), both transports disable peer verification; hostname verification is then only performed when ssl_verify_host => true is also explicitly supplied.
sslVerifyHostThe Stream transport will effectively ignore an explicit ssl_verify_host => true setting in the following situation:
verify => false (or ssl_verify_peer => false).ssl_verify_host value is provided, leaving it at its default.verify_peer => false and, consequently, verify_peer_name => false regardless of the ssl_verify_host flag, because the stream API only honors hostname verification when peer verification is enabled.In contrast, the cURL transport keeps CURLOPT_SSL_VERIFYHOST at its default value (2) even when CURLOPT_SSL_VERIFYPEER is false, so hostname verification may still occur unless you also set CURLOPT_SSL_VERIFYHOST => 0. Therefore, to guarantee identical behavior you must either:
verify at its default (true) and rely on the library defaults, orssl_verify_peer and ssl_verify_host to the same value for both transports.verify => false and ssl_verify_host => true.https://wrong.host.badssl.com/) using both transports.If you need to confirm which transport is active, inspect $client->getTransport() or force a transport via 'transport' => 'yii\\httpclient\\StreamTransport'.
Use comments to ask for clarification. Post a solution as an answer.
32,775 reputation · 07 Jan 2025, 17:58 UTC
The answer correctly notes that ssl_verify_host is ignored when verify => false, but there's a broader constraint: the stream transport cannot disable hostname verification while keeping peer verification enabled. Its verify_peer_name context option is internally coupled to verify_peer — setting verify_peer => true forces verify_peer_name => true in PHP's stream layer.
In contrast, cURL allows CURLOPT_SSL_VERIFYPEER=1 with CURLOPT_SSL_VERIFYHOST=0 (though discouraged). If your security policy requires validating the certificate chain but not the hostname (e.g., connecting to an IP address with a valid cert), the stream transport will reject the connection while cURL can be configured to accept it.
This coupling also affects redirect behavior: cURL re-evaluates both peer and hostname verification on each hop, whereas the stream transport may reuse the original context, causing inconsistent hostname checks after redirects (PHP version dependent). For consistent cross-transport behavior, avoid relying on verifyHost => false and instead use a custom CA bundle via caCert for non-standard hostnames.