Thank you for essentially donating the time you spent on this exploit to raise awareness on improving VS Code's security response. You could have just given up on them but you're still trying to help.
Zooming way out (perhaps to the point of useless observation), it's a pity that the web embedded VSCode editor is signed into GitHub at all. Defense-in-depth or not, a huge vulnerability surface arises from that original sin. It'd be like if you had a god-permissioned GitHub API token stored in world-readable plaintext on your workstation for the malicious-NPM-package-of-the-week to find.
In a perfect world, it'd be awesome if the in-browser IDE launched with a temporary per-repo permission scope or token that allowed only pull and push to the repo in question; no github.com web session whatsoever. If you want the full GitHub web UI experience, well .... go back to github.com; make github.dev a single-repo service.
I'm assuming that's a) inconvenient for users, b) hard to implement, and c) a historical assumption baked into a lot of the github.dev tooling, though. Ah well.
This is going to get worse and worse. I recently noticed AI harness (e.g. OpenCode) downloading random npm packages in the background and litter them everywhere in a few place in ~ and in your project dir, all without telling/asking you.
What's worse is that people don't seem to care even the devs.
I think it's ok to be signed-in when opening your own repositories, but definitely not when opening repositories from other accounts. And also the webview keyboard shortcut thing needs to be fixed to only allow harmless keybinds and NOT propagate to any keydown handler. Also on desktop it should be removed in favor of Electron intercepting directly. And on web it should probably disabled by the default.
You can use SSH keys and GitHub deploy keys to approximate this. Can't speak for the security of it, but I have never set up GitHub with access to every repo. Not sure if there exists approximate functionality in other git forges though.
I think the problem lies in the fundamental design of VS Code extensions in general. They are essentially Node.js apps with full access to built-in modules, including fs. If the corresponding VS Code instance is launched with your user privileges, extensions can technically read files in ~/.ssh.
It is not safe in the sense that for every extension you install, you are essentially installing a new Node.js app with all its bundled dependencies. Even if you trust the publisher, I am sure there are many holes to exploit.
> It'd be like if you had a god-permissioned GitHub API token stored in world-readable plaintext on your workstation for the malicious-NPM-package-of-the-week to find.
Zed is nice, but the project wide search (sidebar based) in VS Code and diff viewer in VS Code are still better IMO and unfortunately since I no longer code, those are my most used features of an editor. Still using it instead of VS Code but I sure wish it improved those views.
Very good write up but I lost it a little at the end. Could someone clarify for me?
The author said:
You cannot just use the shortcut trick to install the evil extension directly because of new publisher trust system;
You can bypass this by using local workspace extensions which has no publisher screening, but CSP blocks it;
The solution seems to be that installing a local workspace extension which binds a shortcut of 'install extension without checking publisher'.
So I assume it means:
1. you need two extensions, 1st one is local and only for the keybinding, and 2nd one is the 'real' evil one and it doesn't need to (actually can't, because of CSP) be local anymore?
2. the CSP only prevents the JS in local extension but nothing about its package.json (or the ability to add shortcuts), right?
github token got stolen and also cloudflare tokens
guys even if you take security seriously you are going to get hit on a long enough time frame
best thing to do is segregate and control damage
trust no one, nothing, use orbstack, and always operate under the assumption that your token is going to get leaked at some point
it knocked off my entire momentum. fortunately seemed like it was just a spam bot that took my tokens and created bunch of fake spam pages and trying to mine crypto
the biggest feeling is the one of feeling violated
> best thing to do is segregate and control damage
I first encountered that concept with a client that put every webapp in it's own virtual server and expected the vm to get compromised at some point. Seemed like a very sensible idea 15 years ago.
I don’t really understand why more devs don’t try Neovim.
Maybe it’s just my preference, but I like having a small setup where I know what is installed and what is running. With VSCode, browser IDEs, extensions, sync, tokens, and random plugins, it gets hard to tell what actually has access to what.
Kudos for the public disclosure. Too many people haven't been happy with MSRC and it's starting to boil over (see the Nightmare Eclipse situation, too). Maybe all of these disclosures will cause them to do some introspection and realize they're the problem. I highly doubt that, but one can dream.
The attack surface that makes this particularly nasty is that VSCode extensions run with the same trust level as the editor itself, and most developers have dozens installed without reviewing their permissions. A malicious or compromised extension silently exfiltrating GitHub tokens is undetectable without network monitoring. This is a good argument for running extensions in isolated profiles.
> The only way to allow this behavior is to have the two web pages in the different origins cooperate with each other using the Window.postMessage() API
Small nitpick, but it's also possible to communicate by changing the location.anchor property (by either the iframe or its parent window.)
49 comments
[ 2.7 ms ] story [ 62.8 ms ] threadZooming way out (perhaps to the point of useless observation), it's a pity that the web embedded VSCode editor is signed into GitHub at all. Defense-in-depth or not, a huge vulnerability surface arises from that original sin. It'd be like if you had a god-permissioned GitHub API token stored in world-readable plaintext on your workstation for the malicious-NPM-package-of-the-week to find.
In a perfect world, it'd be awesome if the in-browser IDE launched with a temporary per-repo permission scope or token that allowed only pull and push to the repo in question; no github.com web session whatsoever. If you want the full GitHub web UI experience, well .... go back to github.com; make github.dev a single-repo service.
I'm assuming that's a) inconvenient for users, b) hard to implement, and c) a historical assumption baked into a lot of the github.dev tooling, though. Ah well.
This is going to get worse and worse. I recently noticed AI harness (e.g. OpenCode) downloading random npm packages in the background and litter them everywhere in a few place in ~ and in your project dir, all without telling/asking you.
What's worse is that people don't seem to care even the devs.
It is not safe in the sense that for every extension you install, you are essentially installing a new Node.js app with all its bundled dependencies. Even if you trust the publisher, I am sure there are many holes to exploit.
That's...exactly what the AWS CLI does.
Someone is going to be blacklisted by Microsoft.
Classic MSRC. It has figured out that researchers will report for free regardless. Why change?
There are probably better sources but I think this video by The Primeagen is a good introduction.
https://www.youtube.com/watch?v=9kxx5xp5nTQ
The author said:
You cannot just use the shortcut trick to install the evil extension directly because of new publisher trust system;
You can bypass this by using local workspace extensions which has no publisher screening, but CSP blocks it;
The solution seems to be that installing a local workspace extension which binds a shortcut of 'install extension without checking publisher'.
So I assume it means:
1. you need two extensions, 1st one is local and only for the keybinding, and 2nd one is the 'real' evil one and it doesn't need to (actually can't, because of CSP) be local anymore?
2. the CSP only prevents the JS in local extension but nothing about its package.json (or the ability to add shortcuts), right?
github token got stolen and also cloudflare tokens
guys even if you take security seriously you are going to get hit on a long enough time frame
best thing to do is segregate and control damage
trust no one, nothing, use orbstack, and always operate under the assumption that your token is going to get leaked at some point
it knocked off my entire momentum. fortunately seemed like it was just a spam bot that took my tokens and created bunch of fake spam pages and trying to mine crypto
the biggest feeling is the one of feeling violated
take care fellow travelers
I first encountered that concept with a client that put every webapp in it's own virtual server and expected the vm to get compromised at some point. Seemed like a very sensible idea 15 years ago.
Github creds or the computer, can't decide which one is worse.
Maybe it’s just my preference, but I like having a small setup where I know what is installed and what is running. With VSCode, browser IDEs, extensions, sync, tokens, and random plugins, it gets hard to tell what actually has access to what.
Small nitpick, but it's also possible to communicate by changing the location.anchor property (by either the iframe or its parent window.)