Resumen
curl mantiene un pool de conexiones y, antes de abrir una nueva, busca si ya hay alguna abierta que sirva para la siguiente transferencia. En el caso de TLS, esa búsqueda tiene que comprobar que la conexión candidata se negoció con la misma configuración de seguridad (verificación del certificado, clave fijada, etc.). Si no lo hace, una transferencia estricta puede acabar usando un canal que se abrió con opciones laxas.
El fallo, publicado por el propio mantenedor de curl (bagder) a partir del hallazgo "F3" de un informe de Andrew Nesbit, está en lib/url.c, en dos funciones del emparejamiento de conexiones (líneas 1024-1036 y 825-844 en el commit 455bebc2c7):
- https://github.com/curl/curl/blob/455bebc2c7/lib/url.c#L1024-L1036
- https://github.com/curl/curl/blob/455bebc2c7/lib/url.c#L825-L844
Los puntos clave:
url_match_ssl_config()solo llama aCurl_ssl_conn_config_match()(la función que compara la configuración TLS) cuando el esquema de la URL buscada tiene la marcaPROTOPT_SSL:
m->needle->scheme->flags & PROTOPT_SSL
- Los esquemas en claro que se elevan a TLS con STARTTLS (
imap://,pop3://,smtp://,ftp://,ldap://junto conCURLOPT_USE_SSL) no llevan esa marca, aunque la conexión acabe cifrada. Por tanto, para ellos la comparación de configuración TLS nunca se ejecuta. - Además,
url_match_ssl_use()(líneas 833-838) permite que una petición con esquema en claro reutilice una conexión ya elevada a TLS gracias aPROTOPT_SSL_REUSE, y la comprobaciónreq_tlsde la línea 840 solo actúa en el caso contrario (cuando la conexión existente no es TLS).
Siguiendo el recorrido para imap:// con USE_SSL, url_match_ssl_use() devuelve verdadero en la línea 838 y después url_match_ssl_config() también devuelve verdadero en la línea 1028 sin haber llamado a Curl_ssl_conn_config_match().
Es la misma familia de fallo que CVE-2022-27782 (reutilización demasiado confiada de conexiones TLS/SSH). Aquella corrección añadió Curl_ssl_conn_config_match, pero detrás de la condición PROTOPT_SSL, de modo que el camino de STARTTLS quedó sin cubrir. Al fallo nuevo se le asignó CVE-2026-8286.
Por protocolo, la situación era:
- IMAP, POP3 y SMTP: no tienen ninguna comprobación propia del protocolo que lo compense.
- FTP:
ftp_conns_matchcompara el nivel deuse_sslyftp_ccc, pero nossl_primary_config, así que tampoco compara la configuración TLS.
Pasos de reproducción
El reporte describe el escenario a partir de la lectura del código, en una misma aplicación que usa curl con conexiones compartidas:
- Un primer handle (A) se conecta a
imap://hostconCURLOPT_USE_SSL=CURLUSESSL_ALLyCURLOPT_SSL_VERIFYPEER=0, es decir, STARTTLS sin verificar el certificado. - Un atacante situado en la ruta de red intercepta la elevación STARTTLS (MITM); como A no verifica el certificado, la conexión se establece igualmente.
- Un segundo handle (B) se conecta al mismo
imap://hostconCURLOPT_USE_SSL=CURLUSESSL_ALL,CURLOPT_SSL_VERIFYPEER=1y una clave pública fijada. - Al buscar conexión, curl encuentra la de A:
url_match_ssl_use()la acepta yurl_match_ssl_config()devuelve verdadero sin comparar configuraciones. - B reutiliza la sesión TLS no verificada de A, y ni la verificación del certificado ni el pinning de B llegan a ejecutarse.
Impacto
Una transferencia configurada para exigir certificado válido y clave fijada podía viajar por un canal TLS interceptado por un atacante en la ruta de red, siempre que antes otra transferencia hacia el mismo servidor y protocolo hubiera abierto la conexión con opciones más laxas. Las garantías que B había pedido (certificado verificado y clave fijada) quedaban anuladas sin aviso. El reporte figura con severidad baja; el escenario exige que la misma aplicación mezcle configuraciones TLS distintas hacia el mismo destino y un atacante en posición de interceptar.
Remediación
El reporte figura como resuelto y con CVE-2026-8286 asignado, pero no detalla el cambio aplicado. El análisis apunta a que la comparación de configuración TLS (Curl_ssl_conn_config_match()) no debe depender solo de que el esquema tenga PROTOPT_SSL, sino de que la conexión use TLS, incluido el caso de STARTTLS.
Qué aprender de este caso
- Cuando una comprobación de seguridad depende de una marca del esquema (como
PROTOPT_SSL), revisa si hay caminos que llegan al mismo estado por otra vía: STARTTLS produce una conexión cifrada desde un esquema "en claro" y se salta todo lo que mire solo el esquema. - En cualquier pool de conexiones (clientes HTTP, de correo, de bases de datos), comprueba que la clave de reutilización incluya todas las opciones de seguridad: verificación de certificado, pinning, certificados de cliente. Si dos peticiones difieren en alguna, no deben compartir conexión.
- Al corregir un fallo, busca sus variantes: aquí la corrección de CVE-2022-27782 añadió la comparación correcta, pero detrás de una condición que dejaba fuera STARTTLS, y el mismo tipo de problema volvió a aparecer por ese camino.
- En código propio, si una aplicación mezcla
VERIFYPEER=0con conexiones estrictas hacia el mismo host, separa los handles o desactiva la reutilización para las conexiones laxas.