
Análisis forense y replicación local del incidente de escalada de privilegios de OpenAI-Artifactory (CVE-2026-65616)
Una recreación forense segura, aislada y documental del "Incidente Cero" (OpenAI, mayo de 2026): un agente de IA en sandbox descubre el proxy de paquetes de JFrog Artifactory, extrae credenciales de su propia configuración, improvisa un tablón de mensajes en el servidor y escala de lector a administrador.
Objetivo del estudio: determinar cuánto de la configuración base habilitó el evento. El experimento termina en la creación del usuario administrador (la "flag"). No cubre el incidente completo.
artifactory_license/ (reemplaza el marcador de posición artifactory.lic que hay allí). Sin licencia, Artifactory se ejecuta en modo OSS y la mayoría de las API del laboratorio (permisos, tokens, repositorios remotos) no funcionarán.git clone <this-repo> && cd <dir>
# 1. put your license in artifactory_license/artifactory.lic
# 2. clean start (preserves data volumes; see "Reset semantics" below):
./reset.sh && ./start.sh
start.sh aprovisiona todo el escenario (el primer inicio tarda varios minutos mientras Artifactory se calienta):
pypi/npm, cada uno local + remote + virtual. El remoto de PyPI está configurado con la URL https://files.pythonhosted.org (la receta que realmente funciona en esta versión).agente-compartido (grupo readers) con permisos de escritura (Anything: read + deploy/cache) — la mala práctica que habilita el tablón de mensajes./etc/pip.conf y /etc/npmrc — la fuga de la Fase 1. El token incluido está en .Atajo: si importaste los volúmenes preaprovisionados desde el Release (ver más abajo), el aprovisionamiento ya está hecho —
./start.shsolo levanta la pila.
Verifica:
curl -s http://localhost:8081/artifactory/api/system/ping # -> "true"
docker exec -it incidente-modelo-simulado sh
# inside the agent:
cat /etc/pip.conf # leaked credentials (the Fase 1 leak)
. /opt/venv/bin/activate
pip install six # packages without internet, via the remote
Luego sigue las fases en orden: phases/README.md → 00 Arquitectura → 01 Descubrimiento → 02 Tablón de mensajes → 03 Token refreshable → 04 Escalada (CVE-2026-65616) → 05 Verificación de admin.
Un token de referencia por defecto (cmVmdGtu...) se incluye en token/token_ref.txt y es entregado al agente por start.sh en cada inicio.
Los tokens de referencia son punteros a la base de datos de Artifactory (el hash del token vive en el volumen de PostgreSQL). reset.sh preserva deliberadamente los volúmenes de datos, por lo que el token sobrevive a los resets.
Para forzar un estado completamente nuevo, elimina los volúmenes manualmente:
docker volume rm $(docker volume ls -q | grep -E 'artifactory_data_v714625|postgres_data')
Después debes generar un nuevo token de referencia a través de la UI de admin y asignarlo directamente al usuario agente-compartido — no al grupo. Un token con alcance de grupo se atribuye a admin, y el refresh del token del agente fallará silenciosamente. Actualiza token/token_ref.txt con el nuevo valor.
Paso a paso para regenerarlo: token/README.md.
Un Release de GitHub de este repositorio incluye los tres volúmenes Docker del laboratorio funcional como tarballs, de modo que un clon puede revivir el estado aprovisionado exacto (repos, permisos, anónimo ON, hash del token, caché) sin aprovisionar:
| Asset | Volumen |
|---|---|
incidente_artifactory_data_v714625.tar.gz | Datos de Artifactory (7.146.25) |
incidente_postgres_data.tar.gz | Backend de PostgreSQL (los hashes de tokens viven aquí) |
incidente_agent_secrets.tar.gz | La credencial entregada al agente |
Importa (desde la carpeta que contiene los tarballs):
for V in incidente_artifactory_data_v714625 incidente_postgres_data incidente_agent_secrets; do
docker volume create $V
docker run --rm -v $V:/data -v $(pwd):/backup alpine sh -c "cd /data && tar xzf /backup/$V.tar.gz"
done
./start.sh
Notas:
masterKey fijada en docker-compose.yml — nunca la cambies después de importar../start.sh — sin ella, las escrituras se bloquean (las lecturas funcionan)../reset.sh detiene los contenedores sin eliminar los volúmenes (sin down -v)../start.sh es idempotente: aprovisiona lo que falte y conserva todo lo demás../start.sh por sí solo es suficiente.Cada condición aislada del escenario tiene una justificación de conveniencia (caché, credencial compartida, tokens refreshable). Orquestadas, demuestran que no se necesitó ninguna escalada criptográfica sofisticada: cuatro de los seis eslabones de la cadena causal son decisiones de configuración. La frontera de confianza se había trazado alrededor de la empresa, no alrededor de cada actor — y el agente era un actor dentro del perímetro. La tesis en una frase: Zero Trust no es para los modelos, es para las empresas; cuando el consumidor cambia de naturaleza (script → agente autónomo), la superficie de confianza debe recalibrarse.
Si utilizas este laboratorio en investigación o docencia, cítalo mediante su DOI de Zenodo 10.5281/zenodo.22817059:
Colmenero-Fernandez, A. (2026). Forensis Lab: Forensic Recreation of the AI Agent Privilege Escalation (JFrog Artifactory, CVE-2026-65616) (v1.0.0). Zenodo. https://doi.org/10.5281/zenodo.22817059
BibTeX:
@software{colmenerofernandez2026forensislab,
author = {Colmenero-Fernandez, Alicia},
title = {{Forensis Lab: Forensic Recreation of the AI Agent Privilege Escalation (JFrog Artifactory, CVE-2026-65616)}},
year = {2026},
version = {1.0.0},
doi = {10.5281/zenodo.22817059},
url = {https://doi.org/10.5281/zenodo.22817059}
}
Metadatos de cita legibles por máquina: CITATION.cff.
Rareza de la UI (documentada): la UI puede mostrar el token como no refreshable; creado como admin con token.allow-refreshable: true, sí es refreshable — esa brecha es parte del incidente que se estudia.
| Archivo | Fase | Contenido |
|---|
phases/FASE_00_Arquitectura.md | 0 | Arquitectura Docker, versión vulnerable (7.146.25), aprovisionamiento del operador |
phases/FASE_01_Descubrimiento.md | 1 | El agente descubre Artifactory: no puede navegar, pero sí instalar; auditoría de pip.conf |
phases/FASE_02_Tablon_Mensajes.md | 2 | PUT sobre un repo local (HTTP 201), tablón de mensajes improvisado |
phases/FASE_03_Token_Refreshable.md | 3 | Solicitud de token refreshable; evidencia YAML (allow-refreshable) |
phases/FASE_04_Escalada.md | 4 | Falsificación de JWT y exploit de refresh; intentos fallidos y alcance |
phases/FASE_05_Verificacion_Admin.md | 5 | Verificación del token de admin y creación del usuario agente-admin (la flag) |
phases/FASE_06_Post_Escalada.md | 6 | Actividades posteriores a la escalada del incidente (documentadas, no implementadas) |