A single click on a link. No download, no install prompt, no warning. Behind the scenes, an attacker walks away with a token that can read and rewrite every GitHub repository you can reach, including the private ones. This is the one-click attack security researcher Ammar Askar disclosed against the web version of Visual Studio Code.

Security researcher Ammar Askar has disclosed a one-click attack against the web version of Microsoft Visual Studio Code that lets an attacker quietly steal a victim’s GitHub access token. The danger is hard to overstate: with that single token, an attacker can read from and write to every repository the victim can touch, private ones included. As Askar put it, just clicking a link is enough to hand over a token that can read and write to a victim’s repositories, including private ones.
|
1
click on a link is all the interaction the attack requires in github.dev
|
ALL
repositories the victim can access are exposed, since the token is not scoped to one repo
|
1 day
from public disclosure (Jun 2, 2026) to Microsoft’s stopgap fix (Jun 3, 2026)
|
The Feature Being Abused: github.dev
The attack targets a genuinely useful GitHub feature called github.dev. Open any repository you have access to, change the address bar from github.com to github.dev (or pick the option from the editor menu), and GitHub drops you into a lightweight version of VS Code running entirely inside your browser. From there you can browse files in private repos, open pull requests, and even commit changes, all without installing anything locally.
That convenience is powered by an OAuth token. When you launch github.dev, github.com hands an OAuth token over to the github.dev environment so it can act on your behalf. Here is the critical design weakness: the token is not scoped to the particular repository you interacted with, which means it carries full access to every other repository you can reach. One token, total reach. If an attacker can pry it loose, they inherit the victim’s entire GitHub footprint.
Why Webviews Are the Soft Underbelly
VS Code is built on Electron, which means executing arbitrary JavaScript inside the main application would be close to full remote code execution. To prevent that, VS Code sandboxes risky content using webviews, the components that render things like Markdown previews and Jupyter notebook output.
A webview is an <iframe> served from a different origin than the main editor window. The main window lives at vscode-file://...; the webview lives at vscode-webview://.... The browser’s same-origin policy keeps them apart, so even if a Jupyter notebook renders custom HTML or runs interactive JavaScript, that code is walled off from VS Code’s core APIs and from Electron’s Node.js integration. In principle, anything nasty inside a webview stays trapped inside the webview.
The problem is that strict isolation breaks the user experience. People expect basic interactions, clicking links, pressing Ctrl+F to search, to work inside a webview just like everywhere else. To make that happen, VS Code uses the browser’s postMessage() API to let the isolated webview and the main window cooperate across the origin boundary, passing small JavaScript objects back and forth. For example, when you move your cursor in a Markdown file, the main window posts a message telling the preview which line to highlight.
The Bug: Forwarded Keystrokes the Attacker Can Forge
Among the messages VS Code forwards across that boundary is a did-keydown event. So that your keyboard shortcuts keep working even when your focus happens to be inside a webview, the webview attaches a keydown listener and bubbles every keypress up to the main window, where VS Code treats those events as if you typed them yourself.
|
Nothing stops malicious JavaScript in an untrusted webview from fabricating keydown events and posting them up as though the user pressed those keys. The attacker can type on the victim’s behalf into the trusted main window.
The core of the vulnerability
|
But it is not as simple as forging Ctrl+Shift+P and typing out a command. Askar found that the Command Palette is a plain HTML <input> element that does not listen for keydown events, so synthetic keystrokes cannot actually type text into it. You can scroll the palette with forged up and down arrows and press Enter, but you cannot type arbitrary strings. The attack has to be assembled entirely from VS Code’s built-in keyboard shortcuts, which do listen directly on keydown.
Chaining Built-In Shortcuts Into Code Execution
The actual exploit chain is more clever than a simple keystroke replay. It assembles ordinary, trusted VS Code features into a path that ends in attacker code running with the victim’s token.
|
1
|
Bait an extension recommendation. The attacker’s repository ships with a .vscode/extensions.json file pointing at their own extension. When the workspace loads, VS Code shows a notification asking whether to install the recommended extension. |
|
2
|
Accept the notification with a forged shortcut. Instead of fighting the Command Palette, the payload fires a synthetic Ctrl+Shift+A (“Accept Notification Primary Action”), which clicks the primary button on the most recent notification, the install prompt. |
|
3
|
Defeat the publisher-trust dialog. Since v1.97, VS Code shows a trust dialog for unknown publishers, and its button ignores forged keys. The attacker sidesteps it with local workspace extensions, which install from .vscode/extensions without a prompt because a trusted workspace (github.dev always is) serves as the trust check. |
|
4
|
Clear the CSP hurdle with a custom keybinding. Local extensions trip a Content Security Policy error on the web build. The attacker’s package.json contributes a custom keybinding (Ctrl+F1) that calls workbench.extensions.installExtension with skipPublisherTrust: true. |
|
5
|
Steal the token. Once active, the attacker’s extension grabs the GitHub OAuth token handed to github.dev, queries api.github.com/user/repos to enumerate every private repository the victim can reach, and exfiltrates both the token and the repo list. |
The full payload is a short script: wait about ten seconds for the recommendation notification to appear, dispatch Ctrl+Shift+A to accept it, wait briefly for the extension to install and register its keybinding, then dispatch Ctrl+F1 to install the attacker’s chosen extension with the publisher check skipped.
Does It Affect VS Code Desktop?
Yes, and this is an important correction to early reporting. The same flaw exists in the desktop version of VS Code. It is simply harder to weaponize there, because the attacker has to convince the victim to clone the malicious repository and open the booby-trapped notebook locally, rather than just clicking a link. And the researcher notes a darker implication: if an attacker combined this with any other cross-site-scripting flaw in a webview, the result on the desktop could be effectively full remote code execution on the victim’s machine.
What VS Code Got Right
The damage could have been worse. VS Code did not rely on the <iframe> boundary alone; it layered on defense-in-depth, including a strict Content Security Policy and DOMPurify sanitization for rendered Markdown. The extension marketplace pages, for instance, are locked down with script-src 'none', which prevents arbitrary JavaScript from running in a Markdown preview. Without those measures, this bug could have escalated into one-click remote code execution simply by sending someone a link to a malicious extension page.
Protecting Yourself
There is a narrow escape hatch. If you have never used github.dev before, landing on the site now presents a sign-in dialog you must click through first, which gives you a chance to navigate away if an attack page loads. The practical defense is to clear cookies and local site data for github.dev. In Chrome, click the icon in the address bar, choose Cookies and site data → Manage on-device site data, and delete the stored data for the relevant domains.
|
The sobering catch
If you have ever clicked past that initial dialog and have not cleared your browser’s local storage, the stored session leaves you exposed. github.dev has no CSRF protection, so any link anywhere on the internet can silently redirect you into this attack.
|
Disclosure and Microsoft’s Response
Askar chose full public disclosure, publishing the bug on June 2, 2026, and filing it on the VS Code issue tracker, after giving a contact at GitHub security a heads-up roughly one hour before going public. He explained the decision by pointing to past frustrations with how Microsoft’s Security Response Center handled earlier VS Code bug reports, including a previous case he says was fixed silently and marked as having no security impact.
Microsoft moved quickly. On June 3, 2026, the day after disclosure, it applied a stopgap fix that adds a confirmation prompt when opening notebooks in web VS Code and blocks commands from skipping the trusted-publisher check, closing off the specific path this exploit relied on.
The Bigger Lesson
This vulnerability is a textbook example of how security and usability pull against each other. Forwarding keystrokes out of a sandboxed webview existed purely to make shortcuts feel seamless, and that small convenience quietly punched a hole through an otherwise solid isolation model. It is also a reminder of why token scoping matters: a github.dev token limited to the single repository a user actually opened would have made this attack far less damaging. Instead, one over-privileged token turned a clever UI trick into full access to a victim’s private code.
