Consider removing workbench.action.terminal.newLocal for extensions using the REH (CVE-2024-49049)
Dear VSCodium maintainers. An issue was filed against my tiny extension (https://github.com/xaberus/vscode-remote-oss) that I cannot fix on my own, as I control none of the affected code. For reasons I cannot fathom VSCode registers an RCE trampoline for remote extension host connections (workbench.action.terminal.newLocal) that a compromised host can use to run arbitrary code on the client side. The best description I found so far is: https://blog.calif.io/p/vibe-hacking-abusing-developer-trust.
Neither my extension nor the other OSS remote extensions use this action. Therefore, I recommend removing the action completely. Todo so you could nuke the registration below https://github.com/microsoft/vscode/blob/main/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts#L24, I guess.
Based on https://fly.io/blog/vscode-ssh-wtf/, it can:
- Wander around the filesystem
- Edit arbitrary files
- Launch its own shell PTY processes
- Persist itself
If that the case, only removing workbench.action.terminal.newLocal won't change the main issue.
This need to be researched and confirmed.
Thanks to bringing up the issue.
@daiyam If I understood the blog post you mentioned correctly, the author mentions "normal" behavior you would expect from a remote extension host. The stuff on the list is what makes the REH useful. Some people dislike that - but they are not forced to use the remote extensions. What I found surprising though, is that the VSCode developers thought it would be wise to include an action that allows the remote host to open a terminal on the client. Honestly, I cannot think of a use case for such an action, especially if there is no functionality included to manage & deny such requests.
I attempted to reproduce the exploit or at least retrace the RPC protocol so far that we can patch the "reverse RCE". Unfortunately, I am not very fluent in this part of code and the implementation of the RPC protocol is a little bit of a callback hell. I will not have much time to investigate this further in the following couple of weeks, so maybe you will have more luck. If it helps, I can try to write up what I learned about the RPC protocol so far...
EDIT: If I had to guess, I would think the clue is hidden somewhere in this abomination of a file: https://github.com/microsoft/vscode/blob/ec0cb2f239dc1fcfb8f5254ed3279e0c484d0869/src/vs/workbench/api/common/extHost.api.impl.ts#L180C1-L181C2
I reproduce a part of the description of CVE-2024-49049 found in cybersecurity news, which summarizes a report
Key Takeaways
- VS Code Remote-SSH extension allows attackers to execute malicious code on developers' local machines.
- Attackers use built-in commands to open local terminals and automatically run arbitrary code.
- Exposing their workstations to compromise when connecting to untrusted servers.
- Malicious extensions on compromised servers can execute the workbench.action.terminal.newLocal command to open a terminal directly on the developer’s local machine, bypassing the remote environment entirely.
- Once the local terminal is established, attackers deploy the workbench.action.terminal.sendSequence command to send arbitrary text sequences to the terminal.
- By appending a newline character, the malicious code executes automatically as if the developer pressed Enter. This technique effectively transforms the trusted development environment into a command and control channel, reads the report.
According to that summary then, the scope of the immediate problem can be narrowed to the functionality of the VS Code Remote-SSH extension or potentially any third party extensions (e.g. xaberus.remote-oss, jeanp413.open-remote-ssh, jeanp413.open-remote-wsl) which facilitate bidirectional communication between local and remote.
Important questions are:
- Do SSH extensions (in general) have the ability to filter/gate arbitrary commands coming from remote to local?
- Does vscodium have the ability to filter commands per extension?
- Could vscodium be modified to (or can it already) route all commands through an extension capable of custom filtering?
I know little about that, but @xaberus might be able to explain more, at least about what the SSH extension is theoretically capable of.
As for wider worries, any evil extension installed on the local vscodium client could act as a conduit to issue commands such as workbench.action.terminal.newLocal and workbench.action.terminal.sendSequence with equal devastation. We know that, and it is another issue worth considering. One workaround is to run vscodium as a remote server and add the extensions there, instead of on local. The we can focus on narrower problem of securing the commands coming from remote, i.e., this issue.
related vscode feature requests:
- https://github.com/microsoft/vscode/issues/52116 [open]
- https://github.com/microsoft/vscode/issues/187386 [closed as duplicate of 52116]
This is compelling security issue... specially with vscode: urls.
The issue isn't in the remote extensions but in the client to accept those connections and commands. For example, open-remote-ssh only download the REH package, install it and start the server, then its job is finished.
Also what about the extension installed on the server that run in UI mode. Won't they have access the client via the UI?
We need a better understanding of the issue so we can see what can be fixed and also how to inform the users.
@craigphicks
As for wider worries, any evil extension installed on the local vscodium client could act as a conduit to issue commands such as
workbench.action.terminal.newLocalandworkbench.action.terminal.sendSequencewith equal devastation. We know that, and it is another issue worth considering. One workaround is to run vscodium as a remote server and add the extensions there, instead of on local. The we can focus on narrower problem of securing the commands coming from remote, i.e., this issue.
No, the evil extension is installed on the remote host but compromises your local client by remotely calling vscode.commands.executeCommand("workbench.action.terminal.newLocal"); which gets translated to your local client. That is what is so insidious about it. You (or at least I) do not expect any valid use for a remote host opening a terminal on my local client.
I reproduce a part of the description of CVE-2024-49049 found in cybersecurity news, which summarizes a report
Can you provide your example extension code?
No, the evil extension is installed on the remote host but compromises your local client by remotely calling
vscode.commands.executeCommand("workbench.action.terminal.newLocal");which gets translated to your local client. That is what is so insidious about it. You (or at least I) do not expect any valid use for a remote host opening a terminal on my local client.
Yes, I understand and I am agreeing with that. I am emphasizing that it is worthwhile solving the narrow problem of filtering commands as they pass through (or out of) the remoss-oss connection.
Note however that others have expressed dismay at the lack of granular permissions and proposed it be fixed. That's a probably a much harder fix, and that proposal was rejected left open years ago, but it would have fixed this problem too.
Can you provide your example extension code?
No promises.
@daiyam OK, so here is my POC. Build it with
npm install
npm run package
Then install it on a remote host. Press F1-> install VSIX. Once installed press F1 -> "Open Local Terminal". The extension should execute echo 'your client might have been composmised right now' in a local terminal on your client.
@xaberus - that is pretty cool. If installed on remote can it try to open back on the client side?
Yes, this is the kind of least-effort evil extension that the blog posts are complaining about. VSCode has no real client/host isolation to speak of. But to provide such a low effort RCE trampoline is just madness... Now the script kiddies don't even have to find a vulnerability to own you. Great job Microsoft!
JFYI, I won't release a new version until I get around that issue.
The command has been there for at least 4 years. Few devs use it (only 3 issues). And VSCode team don't want to promote the command (I wonder why?)...
Also what about the extension installed on the server that run in UI mode. Won't they have access the client via the UI?
More or less. UI extensions are downloaded from the marketplace and installed on the local machine. So bad actors can create a bad extension and have another vector of attack.
The command has been there for at least 4 years. Few devs use it (only 3 issues). And VSCode team don't want to promote the command (I wonder why?)...
Also what about the extension installed on the server that run in UI mode. Won't they have access the client via the UI?
More or less. UI extensions are downloaded from the marketplace and installed on the local machine. So bad actors can create a bad extension and have another vector of attack.
Sorry, I missed your question somehow. Yes "UI" extensions can only run on the local (electron) client. "Workspace" extensions can run on either the electron client or the node REH. If the user chooses to install a compromised extension from openvsx there is nothing we can do about. But here a compromised remote host can locally install a weaponized version of my POC above and take over any client that connects to it without compromising any published extensions or abusing some other code. That is, the vulnerability is unpatchable.
The workbench.action.terminal.sendSequence action on its own is "benign" as long as no local terminal can be created by a remote host. That is why I am proposing to nuke workbench.action.terminal.newLocal, as it is only active for a client connected to a remote host and does not exist otherwise.
Other options might be to implement an action filter on the protocol level or implement some kind of user confirmation. However, both options sound like a lot of effort and are not in the scope of the vscodium project. (Correct me if I am wrong, but the idea was to only remove unnecessary (tracking) parts, not to fix upstream bugs and to implement new functionality. Managing the patches is awkward as it is already...)
This is compelling security issue... specially with
vscode:urls.
In case you are trying to reproduce the vulnerability, the oss remote extensions use different prefixes instead of vscode: but otherwise the behavior is the same.
Correct me if I am wrong, but the idea was to only remove unnecessary (tracking) parts, not to fix upstream bugs and to implement new functionality.
No, you are right. But security targeted features are fine, security is important.
Other options might be to implement an action filter on the protocol level or implement some kind of user confirmation.
I would go for both:
- a new setting that:
- disable the command (by default)
- or, ask permission to the user
- or, leave as is
@xaberus - I compiled and installed your extension "local-terminator" on a remote codium-server. However, after doing so the installation info shows this:
local-terminator
xaberus
Local terminal vulnerability for VS Code
Install Locally
Uninstall
Auto Update
This extension is disabled in this workspace because it is defined to run in the Local Extension Host. Please install the extension locally to enable. [Learn More](vscode-file://vscode-app/usr/share/codium/resources/app/out/vs/code/electron-sandbox/workbench/workbench.html)
Am I mistaken in thinking that the goal is to reproduce the remote vulnerability of being able to open a terminal window with access to the client system via a command from an evil extension installed on the remote server?
If it were possible for a remote extension to run the kind of actions that xaberus.oss-remote runs, but in reverse from remote-server to local-client, e.g. these actions:
"activationEvents": [
"onResolveRemoteAuthority:remote-oss",
"onCommand:remote-oss.openEmptyWindowInCurrentWindow",
"onCommand:remote-oss.openFolderInCurrentWindow",
"onCommand:remote-oss.showLog",
"onView:remoteHosts"
],
that would be a huge risk. But is it possible from the codium-server executable?
Can you test https://github.com/VSCodium/vscodium-insiders/releases/tag/1.104.05841-insider?
It has the PR https://github.com/VSCodium/vscodium/pull/2487 which add command filtering, for now only on or off (by default, workbench.action.terminal.newLocal is off)
The validation is done on the client side. I hope it doesn't slow down the IDE. I have to test that...
@daiyam I tested the insider build and was not able to open a local terminal. The extension host reported a "not authorized" error. However, I was not able to re-enable the "feature" with "workbench.action.terminal.newLocal": true in my settings.json.
@craigphicks I am sorry, you are right. I forgot to commit my last change to the package.json. I updated the repo with the last change. (extensionKind must be workspace not ui, of course...) Now you sohuld be able to open the terminal either from remote or local.
It's "workbench.action.terminal.newLocal": "on". I have to fix the tooltips... It's more a POC.
For the extensionKind, you can always overwrite it with the remote.extensionKind setting.
The version 1.104.05918 should be better.
I've also added the ask option which will prompt the user to validate the command.
stable-1.104.06114 is available with the security patch. Thanks you to have bring up the issue.
Just to understand that:
- Neither extensions nor I can, by default use
workbench.action.terminal.newLocalnow? - I can do that by adjusting a user setting?
If this is the case, then it should not be possible to set this on the remote or workspace settings - obviously...
While I won't see a reason for an extension to use this, I do open local terminals when working on remote spaces (for example to start local or connect to remote servers).
You can by using the settings:
"commands.filters": {
"workbench.action.terminal.newLocal": "ask" // to ask the user for confirmation
// or
"workbench.action.terminal.newLocal": "on" // always authorized
}
The filtering is done on client side.