Most recent
navigate open esc close Corpus index built 2026-06-07 23:58 UTC

← All research

Survey May 14, 2026

Chrome DevTools Protocol, browser-automation backend cloud survey 2026-05-14

NuClide Research

Summary

First population survey of the browser-automation backend tier, opened by triaging 60 named browser-automation / testing / scraping platforms down to the self-hostable, network-exposable subset (see shodan/queries/21-browser-agents.md).

DCWF KSAT coverage

Auto-derived from DCWF AI work-role rule files (ksat-tag).

  • 672 (AI Test & Evaluation Specialist): K7003, K7004, K7044, S7068, S7070, S7075, T5858, T5904
  • 733 (AI Risk & Ethics Specialist): K7051, T5868, T5893
  • overlap (Common AI KSATs (all 5 roles)): K108, K1158, K1159, K22, K6311, K6900, K6935, K7003, K7041, K7048, S7065

The highest-impact target in that set is raw Chrome DevTools Protocol (CDP) on port 9222. CDP is the wire protocol DevTools, Puppeteer, Playwright and Selenium-with-Chrome speak to drive a browser. It has no authentication mechanism, not “auth off by default” like MLflow or Ollama, but no auth concept in the protocol at all. Its only intended boundary is “bound to localhost.” When an operator launches Chrome with --remote-debugging-port and binds it to 0.0.0.0 (or publishes the Docker port, or fronts it with a forwarder), the entire browser becomes remotely controllable by anyone.

A port-first survey of 1,512 Shodan candidates (port:9222 "Content-Type: application/json") was confirmed with a custom read-only CDP probe (GET /json/version + GET /json). Result: 6 confirmed, real, unauthenticated CDP endpoints. 100% exposing browser-level control, plus a 26-host CDP honeypot fleet identified and excluded.

SeverityCountFinding
CRITICAL3CDP unauth + a live authenticated session open (account takeover)
HIGH2CDP unauth, anti-detect scraping farm, adjacent stack exposed
MEDIUM1CDP unauth, idle browser, browser-level ws still controllable
INFO126-host CDP honeypot fleet (threat-intel, not victim infra)

Method: the port-first funnel

1,512  Shodan candidates   port:9222 "Content-Type: application/json"

  ├─ 1,155  http error      → NOT CDP. Host-header retry recovered 0/1155.
  │                           Other JSON service on :9222, no /json/version.
  ├─   272  net error       → firewalled / dead since Shodan's scan
  ├─    52  JSON, no CDP     → genuine collision (JSON svc, not a debugger)

  └─    32  confirmed CDP /json/version
            ├─ 26  HONEYPOT FLEET  → excluded from victim corpus
            └─  6  REAL EXPOSED CDP ENDPOINTS

The 2.1% confirmation rate (32/1,512) is the methodology working as designed: Shodan indexes :9222/ but not /json/version where the identifying webSocketDebuggerUrl lives, so the raw count is a candidate pool, not a finding count. Confirmation requires a direct probe of the sub-path Shodan does not fetch. The same port-first pattern as Methodology Insight #21.

The honeypot fleet (excluded)

26 of the 32 confirmed hosts were a coordinated CDP honeypot fleet:

  • byte-identical Chrome/120.0.6099.109 across 26 unrelated ASNs (Stark Industries, Beget, RackNerd, HostUS, HostPapa, IONOS, Oracle, Linode, MassiveGrid…)
  • uniform 6 open targets, but empty target_types, the decoy fakes /json/version but not a real /json target list
  • 220–340 open ports per host: the respond-to-everything signature

Detection rule (consistent with the AWS Flowise honeypot fleet): absurd port count + identical software fingerprint across unrelated ASNs + malformed secondary endpoint. Cross-checked and dropped before analysis.

The 6 confirmed exposures

HostOrgChromeDriverLive session
24.199.71.227DigitalOcean US148port-forwarderOnlyFans /my/settings
64.23.176.77DigitalOcean US148port-forwarderOnlyFans /my/settings
116.203.42.109Hetzner DE108 (EOL)raw ChromeTicketmaster account
159.195.70.69DXC Technology DK146aiohttp anti-detect farmFilmFans + Google Maps
23.19.231.93LeaseWeb US146aiohttp anti-detect farmAxialy (quant invest)
143.110.166.3DigitalOcean GB144raw Chromeidle (0 targets)

Every host exposes a browser-level webSocketDebuggerUrl, full remote headless-browser control, zero authentication.

Three operator archetypes

The driver behind Chrome, not Chrome itself, is the operator fingerprint. The WebSocket-path shape and HTTP Server header split the six into three classes:

1. Port-forwarder pair. 24.199.71.227, 64.23.176.77 Both expose a ws URL with a /port/35901/devtools/... prefix: a forwarding layer (Docker socat/websockify bridge or a port multiplexer) rewriting CDP paths. Same forwarder port (35901), same Chrome 148, and an identical open-page GUID (96BB7FF88CAC...). This is one operator running a duplicated deployment. Both have a live authenticated OnlyFans session sitting on /my/settings.

2. aiohttp anti-detect farm. 159.195.70.69, 23.19.231.93 The HTTP server on :9222 is not Chrome’s. It is Python/3.12 aiohttp/3.13.5. The root path returns:

{"status":"ok","active":1,"processes":{"__default__":{"pid":13,
 "port":5100,"seed":"71062","connections":2,"timezone":null,
 "locale":null,"proxy":null}}}

Per-process seed, proxy, timezone, locale are anti-fingerprinting controls. Each browser process gets a randomized fingerprint seed and can be pinned to a proxy/timezone/locale. This is a commercial-grade anti-detect scraping farm. Both hosts run the identical aiohttp + Chrome 146 stack. Same software, likely same operator or same off-the-shelf product.

159.195.70.69 exposes its entire backend stack on the same host: :80/443 Traefik (default cert, proxy deployed with no TLS config), :4000 app API, :5432 PostgreSQL 9.6+, :8083 web UI (unauth, /v1/models 200), :8084 API (401), :9090 Prometheus (unauth), :9100 Node Exporter (unauth). The CDP exposure is one port of a fully exposed scraping operation.

3. Raw Chrome. 116.203.42.109, 143.110.166.3 No wrapper. Chrome’s own CDP HTTP server bound directly to 0.0.0.0:9222 instead of loopback. The classic “ran Chrome in Docker, bound to all interfaces to make it reachable, forgot it’s public.” 116.203.42.109 runs EOL Chrome 108 (multiple public RCE PoCs) and has a live Ticketmaster “My Vikings Account” session plus ip.undetect.io open. A ticket-scalping bot caught with its account session exposed.

What the exposure is, technically

An exposed CDP endpoint is unauthenticated remote control of a browser that is already logged into things. Connecting to the webSocketDebuggerUrl and speaking CDP gives an attacker:

CDP commandCapability
Network.getAllCookiesEvery cookie incl. HttpOnly session tokens — DevTools sees through HttpOnly
Runtime.evaluateArbitrary JavaScript in any page’s origin context
Page.navigateDrive the browser anywhere — attacker infra, internal services, 169.254.169.254 cloud metadata
Target.createTargetOpen new tabs even when none exist (why an idle host is still a finding)
Input.dispatchKeyEventSynthesize input — operate the live session as the user
Page.captureScreenshot / printToPDFVisual exfil
Fetch / Network.enableIntercept and rewrite all browser traffic

The impact is not theoretical: three of six hosts have a live authenticated session open right now. Network.getCookies on 24.199.71.227 or 64.23.176.77 returns an OnlyFans session token. Account takeover with no password and no MFA prompt, because the session is already past MFA. 116.203.42.109 is the same for a Ticketmaster account. It also chains: Page.navigate to a Chrome-memory-CVE exploit page on the EOL Chrome 108 host escalates to code execution on the VPS itself.

Auth posture

CDP is the purest case of the auth-on-default thesis. It is auth-never. There is no credential to enable, no config flag to harden. The only mitigations are network-level: bind to 127.0.0.1 (the default that operators override), or firewall :9222. The 100% unauth rate is therefore not a finding about the platform. It is the platform.

New aimap fingerprint

The aiohttp anti-detect CDP server is a discoverable pattern worth adding to aimap: Server: Python/3.12 aiohttp on :9222 + a valid CDP /json/version + a root path returning {"status","active", "processes":{...,"seed","proxy"}}. It points to a specific class of commercial anti-detect browser-automation tooling, distinct from raw Chrome and from port-forwarder deployments.

Cross-references