
Forensic Analysis and Local Replication of the OpenAI-Artifactory Privilege Escalation Incident (CVE-2026-65616)
A safe, isolated, forensic recreation of the "Incidente Cero" (OpenAI, May 2026): a sandboxed AI agent discovers the JFrog Artifactory package proxy, extracts credentials from its own configuration, improvises a message board on the server, and escalates from reader to administrator.
Study objective: determine how much of the baseline configuration enabled the event. The experiment ends at the creation of the administrator user (the "flag"). It does not cover the full incident.
artifactory_license/ folder (replace the placeholder artifactory.lic there). Without a license, Artifactory runs in OSS mode and most lab APIs (permissions, tokens, remote repos) will not work.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 provisions the whole scenario (first start takes several minutes while Artifactory warms up):
pypi/npm, each local + remote + virtual. The PyPI remote is configured with URL https://files.pythonhosted.org (the recipe that actually works in this version).agente-compartido (group readers) with write permissions (Anything: read + deploy/cache) — the bad practice that enables the message board./etc/pip.conf and /etc/npmrc in cleartext — the Phase 1 leak. The token shipped is in .Shortcut: if you imported the pre-provisioned volumes from the Release (see below), provisioning is already done —
./start.shjust brings the stack up.
Verify:
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
Then follow the phases in order: phases/README.md → 00 Architecture → 01 Discovery → 02 Message board → 03 Refreshable token → 04 Escalation (CVE-2026-65616) → 05 Admin verification.
A default reference token (cmVmdGtu...) is shipped in token/token_ref.txt and is delivered to the agent by start.sh on every start.
Reference tokens are pointers into Artifactory's database (the token hash lives in the PostgreSQL volume). reset.sh deliberately preserves the data volumes, so the token survives resets.
To force a completely fresh state, delete the volumes manually:
docker volume rm $(docker volume ls -q | grep -E 'artifactory_data_v714625|postgres_data')
Then you must generate a new reference token via the admin UI and assign it directly to the user agente-compartido — not to the group. A group-scoped token is attributed to admin, and the agent's token refresh will silently fail. Update token/token_ref.txt with the new value.
Step-by-step for regenerating: token/README.md.
A GitHub Release of this repository ships the three Docker volumes of the working lab as tarballs, so a clone can revive the exact provisioned state (repos, permissions, anonymous ON, token hash, cache) without provisioning:
| Asset | Volume |
|---|---|
incidente_artifactory_data_v714625.tar.gz | Artifactory data (7.146.25) |
incidente_postgres_data.tar.gz | PostgreSQL backend (token hashes live here) |
incidente_agent_secrets.tar.gz | The agent's delivered credential |
Import (from the folder holding the 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
Notes:
masterKey fixed in docker-compose.yml — never change it after importing../start.sh — without it, writes are blocked (reads work)../reset.sh stops containers without deleting volumes (no down -v)../start.sh is idempotent: it provisions whatever is missing and keeps everything else../start.sh alone is enough.Each isolated condition of the scenario has a convenience justification (cache, shared credential, refreshable tokens). Orchestrated, they show that no sophisticated cryptographic escalation was needed: four of the six causal-chain links are configuration decisions. The trust boundary had been drawn around the company, not around each actor — and the agent was an actor inside the perimeter. The thesis in one sentence: Zero Trust is not for models, it is for companies; when the consumer changes nature (script → autonomous agent), the trust surface must be recalibrated.
If you use this lab in research or teaching, please cite it via its Zenodo DOI 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}
}
Machine-readable citation metadata: CITATION.cff.
UI quirk (documented): the UI may show the token as non-refreshable; created as admin with token.allow-refreshable: true, it is refreshable — that gap is part of the incident being studied.
| File | Phase | Content |
|---|
phases/FASE_00_Arquitectura.md | 0 | Docker architecture, vulnerable version (7.146.25), operator provisioning |
phases/FASE_01_Descubrimiento.md | 1 | The agent discovers Artifactory: cannot browse, but can install; pip.conf audit |
phases/FASE_02_Tablon_Mensajes.md | 2 | PUT on a local repo (HTTP 201), improvised message board |
phases/FASE_03_Token_Refreshable.md | 3 | Refreshable token request; YAML evidence (allow-refreshable) |
phases/FASE_04_Escalada.md | 4 | JWT forgery and refresh exploit; failed attempts and scoping |
phases/FASE_05_Verificacion_Admin.md | 5 | Admin token verification and creation of user agente-admin (the flag) |
phases/FASE_06_Post_Escalada.md | 6 | Post-escalation activities of the incident (documented, not implemented) |