TL;DR
This is not a (new) vulnerability, but a misconception about the security model many seem to have.
For VS Code remote, the VS Code server is in the same trust boundary as the VS Code client. […]
For Remote SSH, […] A compromised remote could use the VS Code Remote connection to execute code on your local machine.— alexdima on Apr 29, 2022
[…] Dev containers are not designed as a security boundary […]
— chrmarti on Dec 9, 2022
Both alexdima and chrmarti are Microsoft employees, that, according to their GitHub profiles, work on VS Code and Dev Containers, respectively.
1 Introduction
Yesterday, I came across a blog post that describes how to move all development tools to a virtual machine and only run the GUI of Visual Studio Code on the host. This setup is enabled by Microsoft’s Remote Development extensions that also let you run most extensions inside the VM instead of on the host.
However, there is one part about the post that stood out to me:
I do not have any command-line tools installed on the host machine and no transitive dependencies of those to worry about compromising the host. All my development tools and editor extensions are sandboxed in a virtual machine boundary. It’s not perfect security but a useful level of defense […]
The use of VS Code in this way actually undermines most of the security boundary that can exist between host and VM: malicious extensions or code running within the VM could leverage VS Code’s Remote Dev tooling to execute arbitrary code on the host.
I found the post via a Hacker News thread, where, as of writing this post, there’s only one comment that points out this issue. That made it seems to me that this might be a common misconception, so let’s try to understand what could’ve lead people to it and why it’s not true.
2 Confusion over security boundaries
When looking for details about the security model, you’ll find no mentions about it in the general remote [documentation], nor in the Remote Development over SSH or Dev containers tutorials.
Only the Remote Development FAQ includes text like
Some benefits of remote development include:
[…]
Separating developer environments to avoid conflicts, improve security, and speed up on-boarding.
At first, I also misunderstood the above to mean that VS Code’s remote dev can help isolate your local machine from whatever is running on the remote. However, when taking a closer look, you’ll notice that the only other mentions of security in the FAQ are in regards to secure access and transport. Similarly, for Dev Containers the documentation only talks about securely browsing untrusted projects via the Workspace Trust settings that allow code execution only with explicit user consent.
3 Official statements and disclaimers
So I went on to search for for details in GitHub issues, where I found these comments by Microsoft employees and VS Code developers (emphasis added):
For VS Code remote, the VS Code server is in the same trust boundary as the VS Code client. That means that you should only connect to VS Code servers that you trust. So you should only connect to SSH machines that you trust and only create dev containers from definitions that you trust (i.e. you should not use dev containers as a sandbox).
[…]
For Remote SSH, we include the following notice in the extension README:
Only use Remote-SSH to connect to secure remote machines that you trust and that are owned by a party whom you trust. A compromised remote could use the VS Code Remote connection to execute code on your local machine.— alexdima on Apr 29, 2022
The Security Note in the Remote SSH README remains.
[…] Dev containers are not designed as a security boundary and containers are not considered a security boundary in general (there appear to be security hardened container engines). The devcontainer.json can have a “initializeCommand” that will run on the host. The devcontainer.json can bind mount any folder, making it accessible from the container. We forward Git credentials, ssh-agent and gpg-agent sockets into the dev container for convenience.
— chrmarti on Dec 9, 2022
Having a proof-of-concept to achieve code execution on the client would be optimal to see how exactly it can be achieved. But I currently don’t have time to spend on understanding the extension and writing one, so we’ll have to work with the above.
Using the Remote Development or Dev Container extensions can offer some security through obscurity, by relying on attackers not targeting these workflows. But as these extensions/workflows further increase in popularity, I think it’s safe to assume that attackers will increasingly take these kinds of environments into account.
4 Potential future improvements
An issue comment from February 2023 reads: “[…] Perhaps if someone from the VS Code team would provide a few links to any official channels where VS Code security topics are discussed, we could consider this issue good enough to close?”. However, the commenter received no response and I wasn’t able to find any official channels discussing these security topics.
There’s [Feature Request] Extension Permissions, Security Sandboxing & Update Management Proposal from 2018, which proposes a permission model like those used by Chrome or Firefox. However, it doesn’t seem to have made any progress.
Moreover, the only relevant item on VS Code’s roadmap is “Explore sandboxing of extensions in both local and remote scenarios”, which has been there for years without actively being worked on.
That’s essentially all relevant information I found. It leads me to believe that the chance of this situation improving any time soon is low.
5 Better isolation
While it’s probably safe to assume that most devs won’t have to worry about being targeted by VM-escape exploits, limiting the data that’s accessible from the VM without the use of any exploits is likely worthwhile:
- Also move the VS Code GUI to the VM and do not run any dev tools on your host
- Configure a single directory to share with the VM. If folders, mounts, device, etc. of the host are shared with VMs by default, ensure you disable all of that1.
- Use a dedicated VM for each project.
- Share a separate folder with each VM, instead of using a single folder for all VMs
- Only share devices, like printers, with the VM that you actually need
- Consider limiting or disabling clipboard sharing to protect any passwords, API keys and other sensitive data
- Have a look at your hypervisor settings to see if I missed something
If you implement the above, you can be reasonably sure that most malicious dependency updates in one VM won’t affect projects in other VMs or data/credentials on your host.
If you want to additionally limit the chance of being impacted by vulnerabilities in the hypervisor, guest tools, etc., you’ll want to limit the available integration/interfaces between the host and the VM. For example:
- Disable emulation of as many devices as possible
- Consider disabling all sharing (e.g. for Parallels see isolation) between the host and the VM and use tools like Magic Wormhole for file sharing, optionally with a local relay
- For heightened security requirements: do not use/install guest tools whatsoever
For an overview of the hypervisor attack surface and a history of bugs, see Virtualization from an attacker point-of-view by Synacktiv team members.
5.1 Touch ID to authorize copy and paste
One commenter suggests using SSH from the VM to the host to retrieve clipboard contents, while limiting the commands executable via authorized_keys and requiring Touch ID for each request to read or write the host clipboard. In another comment they wrote that allow more commands, which they filter via a script.
It seemed like a good idea, so I worked on a proof of concept for copy and pasting via SSH with Touch ID authorization.Demo
6 Conclusion
Although Visual Studio Code’s Remote Development and Dev Container extensions simplify workflows and ensure consistent development environments, Microsoft’s documentation does not warn about the limited isolation these tools provide – even when used with virtual or remote machines. As a result, many developers mistakenly expect robust security boundaries where none exist.
However, I am not advocating to stop using VS Code’s Remote Dev tooling. Instead, one should make an informed decision on whether it fits your requirements.
If you do require more isolation, a more secure approach involves running all development tools within the VM and deliberately limiting integrations – such as file sharing, clipboard access, and device pass-through – between the host and the VM. This strategy helps ensure that development environments remain isolated and secure, mitigating potential risks associated with unintended interactions between the host and the virtual machine.
Update (2024-02-09): There was an HN thread about fly.io’s “VSCode’s SSH Agent Is Bananas” post, which, judging by some comments I read, didn’t seem to be clear enough. So I adjusted the title to make the issue more obvious, added a TL;DR, and slightly rephrased a few paragraphs.
Footnotes
For example, in Parallels on Mac, selecting the “Software development” profile for a Windows VM configures Parallels to mount the Mac user folder in the Windows VM – and vice versa – and also shares cloud folders and Mac volumes by default.↩︎