devtake.dev

VS Code's webview sandbox leaks GitHub tokens that read and write every private repo

A disclosed VS Code zero-day lets one click on a malicious github.dev notebook steal a GitHub OAuth token with full read-write access to every private repo.

Luca Reinhardt · · 4 min read · 2 sources
Visual Studio Code logo on a dark background
Image via BleepingComputer · Source

A new VS Code zero-day turns one click into a full GitHub account compromise. Security researcher Ammar Askar published a working exploit on June 2 that steals a victim’s GitHub OAuth token the moment they open a booby-trapped notebook on github.dev, and that token isn’t limited to the repo they opened.

This is a different bug from the Nx Console extension breach in May, which leaned on a poisoned Marketplace extension to reach GitHub’s internal repos. Here there’s no extension to install and no Marketplace to trust. The victim clicks a link, and within a minute an attacker is enumerating every private repo the account can see. If you push code to GitHub from VS Code, you’re in scope.

What we know

The danger comes down to OAuth scope: the token github.dev hands your browser isn’t tied to the file you’re editing, it’s tied to your whole account. Steal it once and you’ve stolen access to everything. The mechanics are ugly because they chain together features that all work as designed:

  • It starts on github.dev. When you jump from github.com to github.dev on any repo, github.com POSTs an OAuth token to the github.dev session. As Askar put it, “This functionality is achieved by github.com POSTing over an OAuth token to github.dev that allows it to interact with GitHub on your behalf.” That token has broad scope: “The token is not scoped to the particular repo you interacted with, meaning it has full access to every other repo that you have access to.”
  • The webview is the way in. A malicious Jupyter notebook renders a markdown cell carrying an onerror JavaScript payload inside VS Code’s untrusted webview sandbox. The payload fires synthetic keydown events that bubble up to the main editor without being checked for authenticity.
  • Those fake keystrokes do the work. They accept the extension-install prompt, then trigger a keybind from a local workspace extension dropped in .vscode/extensions. Because it’s a workspace-local extension, it sidesteps publisher trust checks.
  • Then it reads everything. The installed extension grabs the stored token and queries https://api.github.com/user/repos. Read and write. Private repos included.

Askar’s summary is blunt: “Just by clicking a link, it’s possible for an attacker to steal a GitHub token that can read and write to your repos, including private ones.”

The desktop VS Code app is exposed too, not just the browser version. Chain this webview escape with any other webview XSS, Askar notes, “and you get effectively full RCE on their computer” through VS Code’s unrestricted Node.js APIs.

What we don’t know

No CVE was assigned at disclosure, and there’s no patched build to point at. Microsoft’s Security Response Center hadn’t shipped a fix when the exploit went public.

Askar chose full disclosure, notifying GitHub roughly an hour before posting, and he was candid about why. “The last time I interacted with MSRC regarding reporting a VSCode bug, it was a horrible experience where they silently fixed the bug,” he wrote, adding that public disclosure “is one of the few levers I have to try to influence MSRC and the security posture of VSCode.” Whether Microsoft fast-tracks a fix now that a proof-of-concept is in the open is the open question. So is how many repos got touched before anyone noticed, since a stolen token leaves the same audit trail as the legitimate user.

What this means for you

Treat any github.dev token as account-wide until Microsoft ships a fix. The one defense available today is small and manual: clear cookies and local site data for github.dev in your browser, which forces a fresh auth warning if an exploit fires against you. Do that, and don’t open notebooks or repos from links you didn’t expect, especially the “click to edit on github.dev” kind.

For teams, this is a reminder that a developer’s laptop is a credential vault. The same lesson ran through the Nx Console breach, the TanStack npm supply-chain incident, and the GovCloud keys leaked to GitHub: one broadly scoped token is one click away from being someone else’s. Audit which OAuth apps and tokens have org-wide access, prefer fine-grained personal access tokens over the catch-all kind, and assume a compromised dev box means a compromised repo set. My read: rotate anything that smells account-wide and don’t wait for the CVE to land.

Share this article

Quick reference

OAuth scope
The permission boundary on an OAuth token. A narrow scope limits a token to one repo; a broad one grants account-wide access.
RCE
Remote code execution: an attacker runs arbitrary code on the target machine, the worst class of bug.

Sources

Mentioned in this article