Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,62 @@ Related reading on postMessage trust issues:
../../../pentesting-web/postmessage-vulnerabilities/README.md
{{#endref}}


## VS Code / github.dev: synthetic webview shortcuts + declarative extension command bridges

A different VS Code webview escape class appeared in June 2026: **untrusted JavaScript inside a notebook/preview webview could synthesize privileged global shortcuts** because the webview preload forwarded `keydown` data to the host workbench and the host handled it as real user input.

### Boundary failure

If a cross-origin/sandboxed webview copies attacker-controlled keyboard fields (`key`, `code`, `keyCode`, modifiers, `repeat`) into a privileged `postMessage`/message-port bridge **without checking `event.isTrusted`**, JavaScript inside the webview can execute workbench shortcuts with:

```javascript
window.dispatchEvent(
new KeyboardEvent("keydown", {
key: "a",
code: "KeyA",
keyCode: 65,
ctrlKey: true,
shiftKey: true,
})
)
```

This is especially useful when **synthetic typing is blocked** by the browser. Scripted key events usually **cannot type arbitrary text into HTML `<input>` elements**, but they still trigger shortcuts that consume `keydown` directly.

### Practical abuse patterns

- **Shortcut-oriented UI abuse:** target global bindings such as notification acceptance, palette navigation, focused-button activation, or menu movement instead of trying to type commands.
- **Predictable privileged prompts from workspace metadata:** a repository-controlled `.vscode/extensions.json` can recommend an attacker extension and create a predictable install notification that can be accepted with a shortcut such as `Ctrl+Shift+A`.
- **Declarative extension manifest as command bridge:** even if local workspace extension code is blocked by CSP in web VS Code, declarative `package.json` contributions may still load. A local extension under `.vscode/extensions` can register a keybinding that calls `runCommands` and then a privileged internal command such as `workbench.extensions.installExtension`.

Example manifest pattern:

```json
{
"contributes": {
"keybindings": [{
"key": "ctrl+f1",
"command": "runCommands",
"args": {"commands": [{
"command": "workbench.extensions.installExtension"
}]}
}]
}
}
```

- **Hidden security flags reachable from untrusted metadata:** if the internal command accepts attacker-controlled arguments like `{"context":{"skipPublisherTrust":true}}`, declarative metadata can suppress a trust dialog and install a Marketplace/CDN-hosted extension that finally executes attacker code.
- **Trusted-workspace abuse:** if remote/web workspaces are auto-trusted, local workspace extensions become a high-value bridge from repository content to privileged editor actions.
- **Post-compromise scope amplification:** after extension execution, inspect what tokens the editor exposes to extensions. In `github.dev`, the stolen GitHub token was valid beyond the opened repository, so querying `https://api.github.com/user/repos` enumerated additional accessible private repositories.

### Audit notes

- Treat **webview-to-host input forwarding** as a privilege boundary; never re-dispatch synthetic key/click events from untrusted frames into the host.
- Enforce authorization **inside** sensitive commands. Do not accept caller-provided command context that can set internal flags such as `skipPublisherTrust`.
- Do not assume blocking executable local extension code is enough; also review **declarative contributions** (`keybindings`, `menus`, `commands`, tasks) from workspace-controlled manifests.
- The June 3, 2026 fixes added `isTrusted` to forwarded events, disabled untrusted key forwarding in notebook webviews, and stopped accepting caller-supplied install-command context.

## Post-exploitation: ASAR/main-process implants

If you obtain **write access** to an Electron app resources directory, a very practical post-exploitation primitive is to **patch `app.asar`** (or the JS entrypoint it loads) and wait for the user to relaunch the app. Unlike a renderer-only XSS, code loaded from the **main process** executes in the app's **Node.js runtime**, so it can usually access the **filesystem**, spawn commands, hook Electron APIs, and inspect authenticated application state.
Expand Down Expand Up @@ -663,5 +719,10 @@ Detection and mitigations
- More researches and write-ups about Electron security in [https://github.com/doyensec/awesome-electronjs-hacking](https://github.com/doyensec/awesome-electronjs-hacking)
- [https://www.youtube.com/watch?v=Tzo8ucHA5xw\&list=PLH15HpR5qRsVKcKwvIl-AzGfRqKyx--zq\&index=81](https://www.youtube.com/watch?v=Tzo8ucHA5xw&list=PLH15HpR5qRsVKcKwvIl-AzGfRqKyx--zq&index=81)
- [https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)
- [One-Click GitHub Token Theft via VS Code Webview Keyboard Event Injection](https://blog.ammaraskar.com/github-token-stealing)
- [VS Code issue #319593: Webviews can trigger arbitrary keyboard shortcuts in the main workbench](https://github.com/microsoft/vscode/issues/319593)
- [VS Code PR #319705: confirm notebook opening and stop accepting caller-provided installExtension context](https://github.com/microsoft/vscode/pull/319705)
- [VS Code PR #319813: block programmatic webview keypress/click re-dispatch in notebook webviews](https://github.com/microsoft/vscode/pull/319813)
- [VS Code 1.89 / local workspace extensions](https://code.visualstudio.com/updates/v1_89#_local-workspace-extensions)

{{#include ../../../banners/hacktricks-training.md}}