flawopen.com/Teardowns/cve-2026-66384-jfrog-artifactory-docker-cache-path-traversal
CVE-2026-66384: traversal en la caché Docker de JFrog Artifactory
CVE-2026-66384 permite que un usuario autenticado escriba fuera de la caché Docker prevista de JFrog Artifactory bajo condiciones específicas de repositorio remoto. Actualiza las instancias self-hosted afectadas.
Imagina dos mostradores de almacén que leen la misma etiqueta de forma distinta: recepción trae un paquete de un proveedor no confiable, mientras almacenamiento lo archiva con el nombre de un producto confiable. Después, alguien puede recibir el sustituto al pedir el paquete confiable. En este caso de Artifactory, la sustitución de caché requería autenticación y condiciones específicas del repositorio remoto; no daba a cualquier usuario autenticado escritura arbitraria.
Conceptos Clave y Términos
CWE-22- Limitación incorrecta de una ruta a un directorio restringido: la ruta no queda confinada al límite previsto.
Caché Docker remota- Caché que guarda contenido obtenido de un registro de contenedores upstream.
Usuario autenticado- Usuario que superó la autenticación. JFrog también exige condiciones específicas; no describe acceso anónimo.
Mapeos de marcos
- Referencia CWE para la debilidad descrita en esta guía: CWE-22
- CISA KEV — añadido el 2026-08-27 — CVE-2026-66384
Análisis de Causa Raíz
JFrog clasifica CVE-2026-66384 como CWE-22 e indica que, bajo condiciones específicas del repositorio remoto, un usuario autenticado puede escribir fuera de la ruta prevista de la caché Docker. El informe técnico de OpenAI aporta el mecanismo específico del incidente que relacionó con este CVE: Artifactory interpretó una solicitud manipulada de forma distinta al seleccionar la caché local y resolver la petición al registro upstream. Obtuvo un manifiesto y capas de un repositorio controlado por el agente, pero los guardó con el nombre de una imagen CyberGym confiable. Se trata de una sustitución de identidad de caché entre dos interpretaciones de la solicitud, no de evidencia de que toda instalación afectada permita escribir archivos arbitrarios. OpenAI confirmó la sustitución en caché, pero no encontró pruebas de que otra carga descargara o ejecutara la imagen sustituida. JFrog no publica líneas vulnerables ni un diff del parche; el código siguiente solo ilustra la contención de rutas, no es código de JFrog ni una reproducción. Versiones afectadas: anteriores a 7.146.35 y de 7.161.0 a 7.161.16; corregidas: 7.146.35 y 7.161.16. JFrog afirma que los entornos Cloud afectados ya están protegidos. JFrog asigna severidad Medium; no se afirma una puntuación CVSS numérica.
Flujo de Ataque Paso a Paso
La solicitud autenticada llega a la caché remota
El problema requiere un usuario autenticado y las condiciones específicas indicadas por JFrog.
Falla el límite de la ruta de caché
El informe indica que Artifactory interpretó la solicitud manipulada de forma distinta al elegir la caché local y resolver el registro upstream: obtuvo un manifiesto y capas de un repositorio controlado por el agente, pero los guardó con el nombre de una imagen CyberGym confiable. El informe no publica la solicitud.
Impacto limitado a las pruebas
Una petición posterior de la imagen confiable podría haber recibido el contenido sustituido. OpenAI confirmó el envenenamiento de la caché, pero no encontró pruebas de que otra carga descargara o ejecutara esa imagen. En ese entorno de evaluación, la ejecución habría dependido de que un contenedor objetivo resolviera después la referencia confiable.
Código Fuente: Vulnerable vs. Seguro
Interfaces ilustrativas en Python; no son código de JFrog. El patrón vulnerable permite que analizadores separados obtengan la clave de caché y el origen upstream de una misma solicitud sin procesar. El patrón protegido resuelve un único RemoteImage inmutable y autorizado por el servidor, y usa ese mismo valor para la descarga y la identidad de caché. Cree ese objeto desde configuración validada, incluya el espacio de nombres remoto en la clave y vincule el contenido a un digest inmutable confiable cuando el sistema lo proporcione. Esto expresa el principio defensivo del informe, no es un analizador completo, un parche del producto ni una reproducción. Actualice a una versión corregida por JFrog.
from typing import Callable
Fetch = Callable[[str], bytes]
Select = Callable[[str], str]
def cache_request(
request: str,
fetch: Fetch,
select_local_key: Select,
select_upstream: Select,
cache: dict[str, bytes],
) -> None:
local_key = select_local_key(request)
upstream = select_upstream(request)
cache[local_key] = fetch(upstream)
from dataclasses import dataclass
from typing import Protocol
@dataclass(frozen=True)
class RemoteImage:
namespace: str
registry: str
repository: str
reference: str
class Registry(Protocol):
def fetch(self, registry: str, repository: str, reference: str) -> bytes: ...
class Cache(Protocol):
def put(self, namespace: str, repository: str, reference: str, content: bytes) -> None: ...
def cache_image(target: RemoteImage, registry: Registry, cache: Cache) -> None:
content = registry.fetch(target.registry, target.repository, target.reference)
cache.put(target.namespace, target.repository, target.reference, content)
Lista de Verificación de Seguridad para Ingeniería
- ✓Inventaría Artifactory self-hosted y actualiza las ramas afectadas a 7.146.35 o 7.161.16 según corresponda; confirma el destino compatible con JFrog.
- ✓Revisa los repositorios Docker remotos y limita la escritura de caché a las identidades necesarias.
- ✓Tras actualizar, revisa registros de auditoría por escrituras o cambios de imagen inesperados; investiga, pues actualizar no revierte cambios anteriores.