Claude Code sessions exposed a Mac app to the internet

Researchers at Elastic watched a developer's Mac quietly publish a private web app to the public internet, and the process that set it all up was a trusted AI coding assistant.

In a case study published on 7 August, Elastic Security Labs analysts Mika Ayenson and Jia Yu Chan walked through a single July day on a macOS developer laptop where shells launched by Claude Code posted a username and password to an anonymous tunnel address, started a Cloudflare quick tunnel that made a service running only on that laptop reachable from anywhere, and installed LaunchAgents (the macOS equivalent of startup jobs) so the tunnel stayed alive across logouts and reboots. The full walkthrough is in the original report.

The uncomfortable part is the conclusion. Elastic says its telemetry cannot settle whether this was an intrusion or a developer using an agent to expose their own dashboard so they could reach it from outside the office. Both readings fit the same evidence, and the team argues that is now the normal condition for alerts of this kind.

Why it is so hard to call

Coding agents are vendor signed, run all day on developer machines, and are expected to open shells, call APIs, edit files and install helpers. When something suspicious happens underneath one, the parent process looks entirely legitimate. In this window the immediate children were usually plain zsh shells rather than Claude executing every binary itself.

The destinations do not settle it either. The session touched localhost[.]run and its free subdomain space lhr[.]life, Cloudflare quick tunnels under trycloudflare[.]com, and an ngrok binary that Elastic Defend flagged as a hacking tool. All three are legitimate services developers use daily, and all three are also used by attackers to get traffic into a network without opening a firewall port.

How the session unfolded

Elastic reconstructed it in stages. Tunnel and VPN class binaries landed on the host on 20 July. A shell ran a Python script out of /tmp that talked to a remote analytics endpoint on 21 July. Agent child process volume rose sharply on 22 July. Then on 23 July a shell under Claude Code ran a readiness loop that polled a tunnel URL's /login endpoint until it returned HTTP 200, authenticated with credentials passed on the command line, and pulled a spending summary from /api/summary. Cloudflared published the local port to the internet. LaunchAgents named after the app, its tunnels and a watchdog were written with PlistBuddy and loaded with launchctl, with a liveness check confirming the public link was still up.

Two details look damning and are not. The session used a permission bypass flag so tool calls needed fewer human approvals, which is something developers turn on for speed. And the wrapper scripts carried Cyrillic status strings, which Elastic notes adds apparent attribution weight without proving anything at all.

The team also reviewed shorter cases on other hosts: a Cursor agent session that attempted a decrypted keychain dump aimed at OAuth material, which endpoint controls blocked, and a Claude Code session that pulled an unsigned binary over plaintext HTTP and tried to strip its quarantine flag. Elastic is careful to note that one alarming looking command, a keychain read of Claude Code's own token, is documented and expected behavior for that product.

What defenders should take from it

Elastic's guidance is not to suppress these alerts. Credentials on a command line, reverse tunnels and startup persistence should stay high severity even when a signed coding agent is the parent, because the outcome is the same under either reading: a local admin app becomes reachable from the internet and stays that way after the session ends. Shells and temporary files disappear when a session closes. LaunchAgents with a keep alive setting do not.

The practical advice is to name the tunnel provider class early in triage rather than leaning on rare domain or reputation labels, to rebuild the whole session instead of judging single events, and to write down both readings when the evidence supports both. The production rules that fired here were Persistence via GenAI Tool, Unusual Network Connection to Suspicious Web Service and Unusual Network Connection to Suspicious Top Level Domain, and Elastic notes that no single rule covered the full chain.

It is a familiar collision between developer convenience and attacker tradecraft, showing up in a new place. It follows the same pattern as the research on how hidden image instructions can trick AI coding agents into leaking secrets, and the discovery that Fortune 500 firms left AI connector servers open to anyone.

This briefing is provided by IntelFusions for informational and defensive purposes only. It is based on sources assessed to be reliable at the time of writing, and analytic judgments carry the confidence levels indicated. Indicators of compromise are defanged; re-arm them only in controlled environments. IntelFusions is not affiliated with the organizations named and makes no warranty as to completeness or accuracy.

Detection coverage

Read the full analysis on IntelFusions