Casi todo inventario de superficie de ataque arranca con la misma pregunta: ¿qué está expuesto a internet? Es la pregunta correcta, y deja afuera justamente el tipo de falla que CISA agregó al catálogo Known Exploited Vulnerabilities el 17 de agosto de 2026. La CVE-2025-62593 afecta a Ray, el framework de computación distribuida que se usa para entrenar y servir modelos de IA, y no necesita ningún puerto abierto al mundo. Necesita que alguien del equipo de desarrollo abra una pestaña del navegador.

La falla en una frase
La CVE-2025-62593 es una inyección de código (CWE-94, combinada con CWE-352, falsificación de petición en sitios cruzados) que permite a un sitio malicioso enviar peticiones al panel y a la API de Ray que corren en la máquina de quien desarrolla, hasta llegar a la ejecución de comandos arbitrarios. La NVD le asigna un CVSS 4.0 de 9,4, crítico, con el vector CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H, y un CVSS 3.1 de 8,8, alto, con CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H. La diferencia entre las dos notas es justamente la interacción del usuario, que en la práctica significa hacer clic en un enlace o ver un anuncio.
- Afectadas: todas las versiones de Ray anteriores a la 2.52.0
- Corregida en: Ray 2.52.0
- Endpoints vulnerables: /api/jobs/ y /api/job_agent/jobs/, en el puerto 8265 por defecto del panel
- Navegadores que permiten el ataque: Firefox y Safari; Chrome se salva por un bug de implementación de su propia fetch API
- Publicada en la NVD el 26 de noviembre de 2025, agregada al catálogo KEV de CISA el 17 de agosto de 2026
La falla fue encontrada por avilum, de Oligo, y reportada con prueba de concepto por JLLeitschuh, de Socket. El crédito importa acá porque la corrección no fue solo un parche puntual: la versión 2.52.0 también introdujo autenticación por token en el panel, una función que hasta entonces no existía. Conviene notar que esa autenticación viene deshabilitada por defecto, así que actualizar no es el último paso, es el primero.
La defensa que no era defensa: revisar el User-Agent
Ray sabía que las peticiones que llegan desde un navegador eran peligrosas para una API que ejecuta código. La protección implementada fue verificar si el encabezado User-Agent de la petición empezaba con la palabra Mozilla, partiendo de la idea de que solo un navegador envía ese valor y de que un navegador no puede cambiarlo.
# Ray < 2.52.0: a unica barreira contra requisicao vinda de navegador.
def is_browser_request(req: Request) -> bool:
"""Checks if a request is made by a browser like user agent."""
return req.headers["User-Agent"].startswith("Mozilla")
# A premissa: um navegador nao consegue alterar o proprio User-Agent.
# Falsa no Firefox e no Safari, onde a fetch API aceita definir o header.
# No Chrome, um bug de implementacao acabou impedindo a alteracao,
# ou seja, a protecao so funciona por acidente, em um navegador so.La segunda mitad de esa premisa es que existe una lista de encabezados que el JavaScript de una página no puede definir, los llamados forbidden headers. El User-Agent estuvo mucho tiempo en esa lista, y salió. Firefox y Safari implementan la especificación actual y permiten definir el User-Agent en una llamada fetch. Chrome todavía lo bloquea, pero por un defecto de implementación, no por una decisión de seguridad. Una protección que depende del bug de un tercero para seguir valiendo no es una protección, es una ventana de tiempo.
DNS rebinding: el navegador como puente hacia adentro de la red
Romper la verificación de User-Agent no alcanza por sí solo, porque la política de mismo origen del navegador impide que el JavaScript de un sitio lea la respuesta de otro dominio. El DNS rebinding existe justamente para esquivar eso: en lugar de intentar llegar a otro dominio, quien ataca mantiene el mismo nombre y cambia la dirección IP a la que ese nombre resuelve.
# Sequencia de um DNS rebinding, do ponto de vista do navegador.
1) A vitima abre https://site-do-atacante.exemplo
DNS: site-do-atacante.exemplo -> 203.0.113.10 (TTL de 1 segundo)
2) A pagina carrega e o JavaScript apenas espera o TTL expirar.
3) O navegador resolve o MESMO nome de novo:
DNS: site-do-atacante.exemplo -> 127.0.0.1
4) fetch("http://site-do-atacante.exemplo:8265/api/jobs/", { ... })
Para a politica de mesma origem, continua sendo a mesma origem.
Para a pilha de rede, o pacote agora vai para o servico local.El resultado es que el navegador de la víctima pasa a actuar como un cliente HTTP dentro de la red confiable, obedeciendo a un script que controla quien ataca. Eso vale para Ray en el puerto 8265, pero vale igual para cualquier panel administrativo, router hogareño, base de datos de desarrollo o API interna que confíe en el hecho de estar escuchando solo en loopback o en la red local. Desde el punto de vista del navegador, el loopback nunca fue un límite de confianza.
Del /api/jobs al comando arbitrario
Una vez que se llega a los endpoints /api/jobs/ y /api/job_agent/jobs/, el resto es el producto funcionando como fue diseñado. La API de jobs de Ray recibe un campo entrypoint con el comando a ejecutar en el clúster y lo ejecuta. Es para eso que existe. La vulnerabilidad no está en la ejecución, está en que una página web cualquiera pueda llegar hasta esa llamada.
POST /api/jobs/ HTTP/1.1
Host: 127.0.0.1:8265
Content-Type: application/json
User-Agent: laboratorio-interno
{"entrypoint": "id", "runtime_env": {}, "metadata": {}}
# O campo entrypoint e uma linha de comando executada no cluster.
# Aqui usamos 'id' apenas para ilustrar. O ponto do post nao e o
# comando, e o fato de essa requisicao poder partir de uma aba
# de navegador aberta em um site qualquer.En términos de impacto, la estación de trabajo de quien desarrolla modelos suele ser una de las máquinas más interesantes de una empresa. Tiene llave de API de proveedor de nube, token de repositorio privado, credencial de data lake, acceso a GPU y, con frecuencia, copia local de datos de entrenamiento. Un comando ejecutado ahí difícilmente sea el objetivo final de quien ataca, es el punto de partida.
RondoDox, ShadowRay 2.0 y el plazo de tres días de CISA
La línea de tiempo de esta falla tiene un detalle poco común. Según el análisis de Bitsight, la botnet RondoDox empezó a intentar explotar la CVE-2025-62593 el 24 de noviembre de 2025, dos días antes de que la vulnerabilidad se publicara en la NVD. No es el patrón habitual de ingeniería inversa del parche después del anuncio: quien operaba esa botnet estaba mirando el repositorio, no el boletín.
El 17 de agosto de 2026 CISA incluyó la falla en el catálogo KEV, y bajo la directiva BOD 26-04 las agencias federales estadounidenses tuvieron tres días para corregir, con plazo el 20 de agosto de 2026. Tres días es el plazo reservado para lo que ya está siendo explotado de forma consistente, y es una señal razonable de prioridad también para quien no es organismo público estadounidense.
Conviene separar esta falla de una segunda historia que involucra al mismo producto y suele confundirse con ella. La campaña ShadowRay 2.0, documentada por Oligo, explota la CVE-2023-48022, que trata de clústeres Ray con la API de jobs accesible sin autenticación y expuestos directamente a internet. Esa CVE está marcada como disputada, porque Anyscale sostiene que se trata de comportamiento documentado del producto, que presupone ejecución en una red controlada. La campaña convierte clústeres expuestos en botnet de minería de criptomonedas, y Oligo reporta que la cantidad de entornos Ray alcanzables saltó de unos pocos miles a la escala de las centenas de miles.
Las dos historias apuntan a la misma lección por caminos opuestos. En la CVE-2023-48022, el clúster está expuesto y la ausencia de autenticación es por diseño. En la CVE-2025-62593, el servicio no está expuesto y aun así lo alcanzan, a través del navegador. En ambos casos, lo que se rompe es la suposición de que la red resuelve el problema de autenticación.
Qué cambia en el alcance del pentest

En los alcances que nos llegan, la estación de trabajo casi nunca entra, y los servicios locales de desarrollo entran todavía menos. La justificación es siempre la misma: no está expuesto. Esta CVE es un contraejemplo directo, y no es el único. Panel de orquestación de contenedores, notebook de Jupyter, servidor de documentación, herramienta de build con API HTTP, proxy de depuración, todo eso suele levantarse en localhost sin autenticación porque parece un entorno privado.
- Actualiza Ray a 2.52.0 o superior en todos lados, incluidas las estaciones de trabajo, que son el blanco directo de esta falla
- Habilita la autenticación por token de Ray, disponible a partir de la 2.52.0 pero deshabilitada por defecto
- Releva los servicios que escuchan en localhost en las máquinas de desarrollo y trata a cada uno como superficie alcanzable por el navegador, no como entorno privado
- Verifica si algún clúster Ray es accesible desde internet, el escenario de la CVE-2023-48022 y de la campaña ShadowRay 2.0, que es un problema separado y más grave
- Si hay sospecha de compromiso en una estación de desarrollo, rota la llave de nube, el token de repositorio y las credenciales de datos antes de dar el caso por cerrado
- Incluye explícitamente la estación de trabajo y la infraestructura de IA en el alcance del próximo pentest, no como ítem de apoyo, sino como blanco
Este post es educativo y está orientado a la defensa. No publicamos exploit funcional: los fragmentos de arriba reproducen código ya divulgado en el advisory oficial y el uso documentado de la API del producto. Lo que queremos dejar claro es la premisa que falló. Cuando la protección de un servicio es la dirección en la que escucha, quien tiene un navegador dentro de la red ya está del lado de adentro.