The Debug Port Your CI Opens On Purpose
Two of the active threats in this briefing land on the same class of asset — machines you run headless — and neither is fixed by patching. Both are fixed by closing reachable control planes.
Why the tradecraft moved into the live process
Chrome's app-bound encryption made lifting the SQLite cookie store off disk materially harder. So the technique moved to where the plaintext already sits: the running browser. The DevTools Protocol is a WebSocket control plane over the whole browser instance. Target.getTargets enumerates tabs. Network.getAllCookies returns cookies including HttpOnly, and Runtime.evaluate executes JavaScript in the security context of an origin the user already authenticated to. Nothing decrypts, so nothing prompts.
That makes this a session-management failure, not an endpoint one. Single sign-on and MFA gate the transition from anonymous to authenticated. They hold no opinion about a session that is already open, or about a second local process that speaks the browser's own control protocol.
Detection is behavioral, because the protocol is legitimate
Puppeteer, Playwright, and Selenium's CDP bridge do exactly this, routinely, inside the test pipeline. No protocol-level field distinguishes a scraper from an operator, per The Hacker News. There is nothing in the wire format to filter on, so the signal has to come from context: which process launched the browser, with which flags, into which profile directory, and whether anything is listening on a debug port that is not bound to loopback.
- Alert on any non-loopback listener on 9222/9229-style ports.
- Alert on
DevToolsActivePortappearing in an unexpected profile directory. - Push the enterprise policy
RemoteDebuggingAllowed=falseto managed endpoints. - In CI and scraping services, prefer
--remote-debugging-pipeto a TCP port; where a port is unavoidable, bind 127.0.0.1 explicitly.
The Mac fleet is the same shape
macOS Screen Sharing is screensharingd behind ARD/VNC on TCP 5900 and TCP/UDP 3283. It ships off by default. It gets switched on, then port-forwarded, by the people who run Macs headless: colo minis, EC2 mac instances, MacStadium boxes, self-hosted runners doing iOS builds. The Netherlands NCSC reports active exploitation of a patched flaw on internet-exposed Macs, with a Monero miner as the payload. The CVE is not named in the available reporting, so read Apple's security release notes before writing the ticket description.
Cryptojacking is the rational monetization of a machine somebody else pays the CPU bill on, and that sets the detection order. Sustained CPU above 80% during idle windows, week-over-week build-duration regression, and Mac instance-hour spend anomalies all land before any malware verdict does. Block stratum ports and known pool DNS at egress while in there.
Where the two threads agree
Four of the six active items in the threat reporting reviewed here are abuse of legitimate functionality rather than memory corruption: a debug protocol, a remote-desktop daemon, the domain expiry lifecycle, and code-signing trust. None has a patch as its primary fix. The harness research summarized by CSO arrives at the same place from the agent side. The privileges sit in the ordinary code and configuration wrapped around the interesting component, and nobody monitors that layer because it reads as plumbing.
MFA protects the login. Nothing in your stack protects the session, and the tooling that steals it is the same CDP your test pipeline already speaks.
The durable fix is bounded session lifetime, not another blocked port. Scope which admin consoles, cloud-provider logins, and internal SaaS sessions currently survive a raw cookie export, then investigate device-bound session credentials and short-TTL-with-rebind for the ones that do. Port closure buys time. Session binding is what makes the next variant of this technique boring.
What to do
Grep every CI config and Dockerfile for --remote-debugging-port this week, switch to --remote-debugging-pipe or an explicit 127.0.0.1 bind, and push RemoteDebuggingAllowed=false to managed endpoints.
Scan the full Mac estate — colo minis, EC2 mac instances, MacStadium boxes, self-hosted runners — for reachable TCP 5900 and TCP/UDP 3283 by Friday, disable com.apple.screensharing where unused, and block both ports inbound at the perimeter firewall for every host that still needs the service; name an owner this week to choose between WireGuard and Tailscale and to schedule the bastion migration as its own tracked project.
Add two detections this sprint: any non-loopback listener on 9222-class ports, and sustained idle-window CPU above 80% on build hosts with stratum egress blocked.