Stealing GitHub Tokens via a One‑Click VSCode WebView Exploit

The article details how a VSCode WebView vulnerability lets an attacker capture the OAuth token issued to github.dev, use keyboard‑event relay to install a malicious extension, and ultimately gain read‑write access to all of a victim’s private GitHub repositories, while also providing a PoC and mitigation steps.

Black & White Path
Black & White Path
Black & White Path
Stealing GitHub Tokens via a One‑Click VSCode WebView Exploit

Background

github.dev provides a lightweight, browser‑based VSCode experience that can view any repository, including private ones, and perform actions such as creating pull requests and committing code. When a user accesses github.dev, it sends a POST request to GitHub to obtain an OAuth token that represents the user’s full repository permissions, not just the current repository. The token grants read‑write access to all repositories the user can access.

VSCode WebView security model

VSCode, built on Electron, isolates JavaScript execution in WebViews using separate origins via <iframe>. The WebView content (e.g., Markdown preview, Jupyter Notebook) runs under a vscode-webview://... origin, while the main Electron window uses vscode-file://.... Communication between these origins is limited to the Window.postMessage() API.

Keyboard shortcuts are implemented by registering a did-keydown event listener in the WebView, which forwards key events to the main VSCode window:

contentWindow.addEventListener('keydown', handleInnerKeydown);

const handleInnerKeydown = (e) => {
    hostMessaging.postMessage('did-keydown', {
        key: e.key,
        keyCode: e.keyCode,
        code: e.code,
        shiftKey: e.shiftKey,
        altKey: e.altKey,
        ctrlKey: e.ctrlKey,
        metaKey: e.metaKey,
        repeat: e.repeat,
    });
};

These forwarded events are treated by VSCode as genuine user input, allowing the WebView to trigger any command that has a keyboard shortcut.

Keyboard event relay attack

Pressing Ctrl+Shift+P inside the WebView opens the command palette, but synthetic keydown events cannot type arbitrary text because the input element only listens to real keydown events. VSCode ships many built‑in shortcuts that listen directly to keydown. The attacker can use the "Accept Notification" shortcut Ctrl+Shift+A to click the primary button of the most recent notification.

VSCode can show a recommendation notification for installing an extension defined in .vscode/extensions.json. From VSCode 1.97 onward, installing an extension from an untrusted publisher triggers a trust dialog that only listens to keydown events on the dialog buttons, making automation harder.

By placing a local workspace extension in .vscode/extensions, the attacker bypasses the publisher‑trust check because extensions installed from the workspace directory skip the check. The malicious extension can contribute a custom keyboard shortcut that runs a command to install another malicious extension.

The full attack chain requires:

Waiting for the extension‑recommendation notification to appear.

Sending Ctrl+Shift+A to accept the notification.

Installing the malicious extension, which registers a custom shortcut.

Sending the shortcut (e.g., Ctrl+F1 ) to trigger the extension’s payload.

Proof‑of‑Concept

The PoC repository is located at

https://github.dev/ammaraskar/github-dev-token-steal-poc/blob/main/README.ipynb

. Opening the notebook in github.dev runs a JavaScript payload that installs the malicious extension, which then reads the OAuth token, queries the list of private repositories via the GitHub API, and displays the list in an information box.

Mitigation

Clear github.dev cookies and site data. In Chrome, open the site‑data manager (Cookie and site data → Manage site data) and delete entries for github.dev. If storage was not cleared, the attack succeeds because github.dev lacks CSRF protection.

VSCode defenses

VSCode employs depth‑defense measures such as a strict Content Security Policy (CSP) that includes script-src 'none', and uses DOMPurify to sanitize rendered Markdown. These measures block arbitrary script execution in extension previews.

VSCode WebView security boundary diagram
VSCode WebView security boundary diagram
Markdown preview highlighting source line
Markdown preview highlighting source line
WebView security boundary
WebView security boundary
VSCode extension recommendation notification
VSCode extension recommendation notification
Publisher trust dialog
Publisher trust dialog
PoC initial page
PoC initial page
Extension view CSP
Extension view CSP
Initial login dialog
Initial login dialog
Chrome site data management
Chrome site data management
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

WebViewExtensionVSCodeOAuthSecurity VulnerabilityPoCGitHub token
Black & White Path
Written by

Black & White Path

We are the beacon of the cyber world, a stepping stone on the road to security.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.