← Tools I Use

A VS Code extension can steal your GitHub token in one click — and the token isn't scoped to one repo

2026-06-04 · ~7 min read · Conor Dobbs

On June 3, security researcher Ammar Askar published a working VS Code zero-day: a malicious extension can lift your GitHub OAuth token with a single click. He gave GitHub one hour of notice before going public. The token it steals is not scoped to the repo you were working in. It is good for every repository you can reach.

That last detail is the part worth sitting with. The headline is "VS Code zero-day steals GitHub tokens," but the bug is more interesting than a token grab, and the reason it got dropped with one hour of warning is more interesting than the bug.

What actually happens

The attack chain runs through github.dev, the browser-based VS Code you get when you press . on a GitHub repo. When that editor loads, github.com hands it a GitHub OAuth token by POSTing it into the page so the editor can read and write your repos on your behalf. Convenient, and the kind of thing nobody thinks about because it is invisible.

VS Code extensions render their UI inside sandboxed webviews, and those webviews talk back to the editor through a message-passing channel. Askar's finding is that a malicious extension can run JavaScript inside its webview that abuses that channel — in his demonstration, by simulating keypresses — to reach the context holding the OAuth token and exfiltrate it. One click on the wrong extension's UI, and the token is gone.

The token is the prize, and the scoping is what turns a nuisance into an incident. As Askar put it, the token is not scoped to the particular repo you interacted with. It is an account-level credential. Whoever holds it can read your private source, push commits, open and merge pull requests, and reach anything your account can reach until you notice and revoke it. There is no CVE assigned as of this writing.

If you use github.dev, clear its cookies

The cheap, immediate mitigation does not depend on Microsoft shipping anything. In your browser, clear the cookies and on-device site data for github.dev (Settings → Privacy → cookies and site data → manage on-device data, depending on your browser). That drops the cached session, so the next time you open the web editor it makes you sign in again instead of silently re-receiving a token. It is a thirty-second hygiene step that closes the silent-reuse window.

Microsoft's position is that it mitigated the issue for its own services and that no customer action is required. Take that at face value for github.dev itself, but the broader lesson — an extension can reach a credential it has no business touching — is not something a server-side patch retires. Which extensions are you running in your editor right now, and what could each of them read if it decided to?

Your editor is part of your supply chain now

We have spent the last month writing about supply-chain compromise — the self-propagating npm worm, auth tokens leaking through published packages, poisoned dependencies. The common thread is that the code you run is rarely just the code you wrote. This zero-day extends that line into the editor itself.

A VS Code extension is not a passive theme. It is a program running with the editor's privileges, inside the same process boundary as your source, your terminal, and — as this bug shows — your tokens. The marketplace makes installing one feel like adding a browser bookmark, but the trust you extend is closer to running an unsigned binary you found in a forum. Most extensions are fine. The model that lets the bad one reach your GitHub token is the problem, and that model is the same whether the extension is malicious or simply compromised upstream, the way a popular npm package can be.

The defensive habits here are unglamorous and they work. Audit your installed extensions and remove the ones you do not actually use. Prefer publishers you can name. And scope your credentials so that a single stolen token is a contained loss, not a domain-wide one — which is exactly the property this bug violated.

Scope the token, shrink the blast radius

The reason one stolen token here is so costly is that it carries account-wide reach. That is a design choice, and it is one you can push back on for your own credentials. GitHub's fine-grained personal access tokens let you grant a token access to a specific set of repositories and a specific set of permissions, instead of the classic all-or-nothing scopes. CI that only needs to read one repo should hold a token that can only read one repo.

None of that would have stopped the github.dev token theft — that token is minted by GitHub, not by you. But it is the same principle, applied everywhere you do control it: the cost of a leaked credential should be bounded by what that credential could do, and most credentials in most pipelines can do far more than the job in front of them requires. A breach is a question of when; the size of it is a question of scoping you decided in advance.

The disclosure breakdown is the real story

Now the part that should worry a security team more than any single extension bug. Askar did not sit on this for ninety days. He gave GitHub one hour. His stated reason: a previous VS Code bug he reported to Microsoft's Security Response Center was, in his account, silently fixed with no credit and marked as having no security impact. So this time he skipped the process and published.

He is not alone. The same week, a separate researcher operating as "Nightmare Eclipse" was dropping multiple Microsoft zero-days with no advance notice at all, and Microsoft publicly criticized the wave of unembargoed disclosures, reportedly including the removal of a researcher's GitHub account. You can read that as researchers behaving badly. I read it the other way. Coordinated disclosure is not a courtesy researchers owe vendors; it is a trade. The researcher absorbs the cost of waiting in exchange for being treated fairly — credit, acknowledgment, an honest severity rating. When a vendor is perceived to take the silence and skip its side of the trade, the rational move for the next researcher is to stop waiting. One hour of notice is what a broken disclosure process looks like from the outside.

That has a direct cost to everyone downstream. The thing standing between "a researcher found a bug in your editor" and "a working exploit is public before there is a fix" is not a tool. It is whether that researcher trusts your process enough to give you time. Microsoft can patch github.dev in a day. Rebuilding the goodwill that buys it a quiet ninety-day window takes a lot longer, and the bill for losing it is paid by every user who runs the editor.

The takeaway that outlasts this bug

Patch when the fix lands, clear your github.dev cookies today, and prune the extensions you do not need. Those close this particular hole. The habits worth keeping are bigger than one zero-day: treat your editor and its extensions as untrusted code running next to your credentials, scope every token so a single theft is survivable, and — if you are on the vendor side of this — remember that your disclosure process is itself a security control. When researchers stop trusting it, you do not get fewer bugs. You get the same bugs, published first.

Sources