Composer token leak May 2026
What triggers the Composer token leak vulnerability, which CI setups are critical, how to patch — and which token TTLs you must assume for self-hosted runners and GitHub Apps.
3 June 2026. On 2 June, security researcher Ammar Askar published, via full disclosure, a flaw in VSCode's webview architecture that allows a single click on a github.dev link to exfiltrate the victim's GitHub OAuth token — with full read and write access to all repositories, including private ones. No patch exists at the time of publication.
One click on a crafted github.dev link is enough to steal the GitHub OAuth token with full access to all repos. No patch available; mitigation only via clearing browser site data.
| Question | Answer |
|---|---|
| Affected? | Every developer who has ever used github.dev and whose browser still holds local site data (cookies, local storage) for github.dev. Desktop VSCode is affected too, there with a higher exploit bar (clone repo + open notebook). |
| Risk? | Complete GitHub OAuth token theft: read and write access to all of the victim's repos, including private ones. The token is not scoped to the specific repository opened. On desktop VSCode: remote code execution. |
| Immediate measure? | Clear browser site data for github.dev (cookies, local storage, IndexedDB). Don't click unknown github.dev links. On desktop VSCode: don't open Jupyter notebooks from unknown repos. |
| Recommendation? | Mittelstand: clear site data immediately, team awareness, review the GitHub audit log for unknown token use. Enterprise: central browser policy for github.dev site data, GitHub Enterprise audit-log review, evaluate Codespaces as an alternative to github.dev. |
| Criticality? | See the hero badge — high |
VSCode renders content from extensions and features such as Markdown previews or Jupyter notebooks in so-called webviews. Technically these are <iframe> elements with their own origin (vscode-webview://), isolated from the application's main origin. This isolation is the central security boundary: JavaScript running inside a webview cannot access VSCode's internal APIs, the file-system layer or the Electron Node.js context. Communication between the webview and the VSCode main window runs exclusively through the Window.postMessage() API, a controlled message channel without direct DOM access.
The problem lies in how VSCode transports keyboard input across this boundary. So that keyboard shortcuts like Ctrl+Shift+P (command palette) still work when focus is inside a webview, VSCode registers a keydown event listener in the webview and forwards every keystroke via postMessage to the main window. The main window treats the forwarded events as if they came directly from the user.
This is exactly where it breaks: JavaScript code running inside the webview (which the sandbox model should keep contained) can create synthetic keydown events and send them over the same postMessage channel to the main window. VSCode does not distinguish between real keyboard input and synthetic events from the webview. An attacker can thus trigger arbitrary keyboard shortcuts in the context of the VSCode main window.
Security researcher Ammar Askar built a complete exploit chain from this. The entry point is a Jupyter notebook in a GitHub repository. Jupyter notebooks can render HTML, including <img> tags with onerror handlers — a known way to execute JavaScript in the webview context. From there the exploit uses four steps:
First, the script waits until VSCode shows a notification prompting installation of a recommended extension (the repository contains a .vscode/extensions.json recommending a local workspace extension). Second, the script simulates Ctrl+Shift+A (the shortcut for „Accept Notification Primary Action“) to confirm the installation. Third, it waits until the local extension is active. This extension brings its own keybinding (Ctrl+F1) that triggers the command workbench.extensions.installExtension with the parameter skipPublisherTrust: true. Fourth, the script simulates Ctrl+F1 to install a second extension from the VSCode Marketplace, which now has full access to VSCode's extension API and reads out the GitHub OAuth token.
On github.dev the attack is especially effective because, when a repository is opened on github.dev, github.com hands over an OAuth token via POST that is not scoped to the specific repository — it has full read and write access to all of the user's repos, including private ones. Anyone who has once clicked through the initial sign-in dialogs on github.dev and has not cleared the site data is compromised on clicking a crafted link, without any further interaction.
On desktop VSCode the attack is also possible but requires the victim to clone the crafted repository and open the notebook in the editor. The impact there is more severe: instead of token theft, the attacker has full access to the Node.js context via the extension API, i.e. remote code execution on the developer's machine.
The researcher published the bug via full disclosure, without prior coordinated reporting to Microsoft's Security Response Center (MSRC). In his post he justifies this with earlier negative experiences coordinating VSCode bugs with MSRC: an earlier report was silently fixed, without credit, and classified as not security-relevant. A proof of concept is publicly available.
The attack vector has two variants with different entry bars and blast radii.
| Constellation | Affected | Not affected / conditions |
|---|---|---|
Developers who have ever used github.dev and still hold its site data in the browser | 1-click exploit — one click on a crafted github.dev link is enough. No clone, no local file access needed. Token theft with full repo access. | Developers who never used github.dev or whose browser site data for github.dev has been cleared (the login dialog blocks the auto-exploit) |
| Desktop VSCode users with the Jupyter extension | When a notebook from an unknown repository is opened — remote code execution on the developer's machine | Notebooks from trusted own repos; users without the Jupyter extension (though other webview-XSS vectors would be conceivable) |
| GitHub Codespaces | Potentially affected, since Codespaces run VSCode in the browser — the exploit path via webview keydown forwarding is structurally identical | Codespaces use a different token scoping than github.dev; the exact blast radius is unclear |
| TYPO3/Sylius platform operators with private GitHub repos | Indirectly affected: if a developer with write access to the platform repo is compromised via github.dev, the attacker has full push access to the platform code — LocalConfiguration.php templates, CI secrets mappings, deployment manifests | Platforms on GitLab, Bitbucket or self-hosted Git instances are not affected by this specific attack vector |
| CI/CD pipelines with GitHub Actions | Not directly affected by this bug — the exploit path goes through the developer's browser, not the pipeline. But: a stolen token has contents: write on all repos and can manipulate workflow files — the attack can propagate into the pipeline | — |
| Organisations with GitHub Enterprise Cloud or GHES | Affected if members use github.dev for enterprise repos. The token grants access to all repos the compromised user can access — including organisation repos | Organisations that have disabled github.dev by policy |
The combination of 1-click exploit, unrestricted token scope and missing patch makes the github.dev vector the more operationally relevant of the two paths. Desktop VSCode is technically harder, but in impact (RCE on the developer's machine) potentially more severe.
What makes this bug operationally serious is not the complexity of the exploit but the combination of three factors: the trivial entry bar (one click), the unrestricted token scope (all repos, read+write), and the fact that no patch exists at the time of publication.
The OAuth token exfiltrated via github.dev is not scoped to the repository the user is currently viewing. It has full read and write access to all repositories the GitHub account can access. In a typical German Mittelstand setup with three to ten private organisation repos plus the developer's personal repos, that means: a single compromised developer account exposes the organisation's entire code base.
Write access to repositories is the most critical lever in supply-chain architecture. An attacker with push rights can place commits directly on the main branch, manipulate tags, alter GitHub Actions workflow files, and overwrite release artifacts. On a TYPO3 or Sylius platform whose deployment pipeline hangs off GitHub tags or branches, that is the direct path into production — not through a flaw in the application itself, but through the supply chain of the platform code.
On desktop VSCode the impact goes beyond token theft. The installed extension has full access to the Node.js context of the Electron process, i.e. remote code execution with the rights of the logged-in user: file-system access, network access, process spawning, SSH-key exfiltration, credential-store access. The classic „clone a repo and open it“ hurdle is no serious obstacle for targeted social engineering. A message like „Can you take a quick look at this notebook?“ is enough in many team contexts.
The full-disclosure character sharpens the situation. The proof of concept is public, reproducible and documented. The time between publication and patch (if Microsoft ships one) is the operational risk window. Anyone who clicks a github.dev link from an unknown source in this window is potentially compromised.
As long as no patch from Microsoft is available, the only complete mitigation is removing the persisted sign-in state on github.dev. Three operational paths by urgency.
In Chrome: address bar → click the lock/info icon → „Cookies and site data“ → „Manage on-device site data“ → delete all domains under github.dev (cookies, local storage, IndexedDB, service workers).
In Firefox: Settings → Privacy & Security → Cookies and Site Data → Manage Data → filter for „github.dev“ → Remove Selected.
In Safari: Settings → Privacy → Manage Website Data → search for „github.dev“ → Remove.
After clearing, github.dev shows a login dialog on the next visit. This dialog interrupts the automatic exploit chain — the user can leave the page before the attack takes hold. It is not a complete safeguard, but it turns a 0-click exploit (for users with a persisted login) into an attack that requires a deliberate sign-in.
Until Microsoft ships a patch: don't click github.dev links from external sources. For quick code reviews on GitHub, use the regular github.com interface or the GitHub mobile app instead of the .dev variant. If you need the full editor: evaluate GitHub Codespaces as an alternative — Codespaces have different token handling, but the exact level of protection against this specific exploit is not conclusively established.
On desktop VSCode the exploit path is narrower: the victim must clone a crafted repository and open a Jupyter notebook. The mitigation is organisational. Don't open .ipynb files from unknown or unvetted repositories until VSCode patches the webview keydown-forwarding mechanism. VSCode's workspace-trust mechanism does not protect here, because local workspace extensions may be installed in trusted workspaces and github.dev workspaces are trusted by default.
Anyone who opened a github.dev link from an external source in recent days and is unsure whether the link was crafted:
# Check the GitHub audit log for unknown OAuth token use (personal account)
# Settings → Developer settings → Personal access tokens → review token list
# Settings → Applications → Authorized OAuth Apps → identify unknown apps
# For organisations: audit log for token creation and repo access
gh api /orgs/<org>/audit-log \
--jq '.[] | select(.action | startswith("oauth_application")) | {action, created_at, actor}'
GitHub App installation tokens issued via github.dev have a limited lifetime. The OAuth token github.com hands to github.dev via POST is a longer-lived session token. Anyone suspecting compromise should revoke all active OAuth sessions on GitHub: Settings → Sessions → „Revoke all“.
Three complementary paths — one at the GitHub platform level, one on the developer's machine, one at the organisation level.
At the organisation level, the GitHub audit log shows whether tokens were used for unusual repo access — in particular access to repos the user does not normally open via github.dev:
# Organisation audit log: repo access in the last 72h via the REST API
gh api "/orgs/<org>/audit-log?phrase=action:repo.access+created:>$(date -u -d '72 hours ago' +%Y-%m-%dT%H:%M:%SZ)" \
--jq '.[] | {actor: .actor, repo: .repo, action: .action, created_at: ."@timestamp"}'
Specifically check: access to repos the user does not typically work on, and push events from users who normally only read.
On the developer's machine, check the extension list for unexpected installs:
# List installed VSCode extensions
code --list-extensions --show-versions
# Filter for unknown publishers — let known publishers through
code --list-extensions | grep -v -E "^(ms-|github\.|redhat\.|esbenp\.|dbaeumer\.)"
On github.dev: in the browser DevTools tab (F12) → Application → Local Storage → look for extension IDs that don't belong to your own working environment.
The proof of concept exfiltrates the token via an HTTP request to api.github.com/user/repos. A real attacker would send the token to their own endpoint. In browser DevTools (network tab) or via a corporate proxy log, identify outbound connections from github.dev tabs that don't go to github.com, github.dev or vscode-cdn.net domains.
The operational question is not „does this affect us?“ — it is „how many of our developers used github.dev in recent months and still have the site data in the browser?“. If you don't know the answer, treat the estate as „potentially exposed“ and take the audit path.
Clear github.dev site data as a team communication to all developers with GitHub access. No technical infrastructure change needed; the mitigation is one browser action per person plus the discipline not to open unknown github.dev links. Spot-check the GitHub audit log for unusual push events and token creation in the last 72 hours. If platform code (TYPO3 sitepackages, Sylius plugins, deployment manifests) lives on private GitHub repos: check the commit history for unknown commits, especially changes to .github/workflows/ files. That would be the follow-on path of a token exfiltration into the CI pipeline.
Evaluate a central browser policy for github.dev site data. Chrome Enterprise policies allow targeted clearing of site data per domain (CookiesBlockedForUrls for github.dev as an interim solution until a patch is available). Run the GitHub Enterprise audit log at organisation level with the detection script from the previous section, extending the window to the last 7 days. Evaluate GitHub Codespaces as an alternative to github.dev — Codespaces offer a more isolated environment, albeit at higher cost and infrastructure requirements. Additionally: verify repository branch-protection rules on all critical repos. A stolen token can only push directly to main if no branch protection is active.
The attack vector goes through the developer's browser, not the cluster infrastructure. The cluster platform is only indirectly affected if deployment manifests or Helm charts live on private GitHub repos and a compromised token is used to push changes there. GitOps stacks (ArgoCD, Flux) that point to GitHub repos as the source of truth should enable commit-signature verification (--verify-signatures) — a commit pushed via a stolen token without a GPG signature is then not deployed automatically.
Affects the flake/configuration repos if they are hosted on GitHub. The mitigation is the same as at the Kubernetes level: commit-signature verification in the GitOps pipeline plus site-data clearing for developers with push access. Nix flake locks and Wolfi package manifests are especially sensitive targets, because manipulation there affects the entire build chain.
Potentially yes. The webview architecture and the keydown-forwarding mechanism are part of the VSCode codebase these forks inherit. Whether the specific exploit chain (Jupyter notebook + local workspace extension + keybinding) works in every fork depends on the respective extension support and webview configurations. The structural weakness — that synthetic keydown events are not distinguished from real ones — is built into the shared codebase.
At the organisation level yes, the GitHub audit log shows repo access, push events, token creation and OAuth-app authorisations. At the personal-account level the audit view is more limited: Settings → Security log shows login events and session activity, but not every API call against the token. If you suspect misuse, additionally check the commit history of all your own repos for unknown commits. A stolen token with contents: write leaves the trace of a push in the Git log without the usual GPG signature.
The researcher justifies the full-disclosure approach with earlier negative experiences reporting VSCode bugs to Microsoft's MSRC: an earlier report was silently fixed, without credit and classified as not security-relevant. Regardless of how one judges the disclosure approach, the operational consequence for platform operators is the same: the exploit is publicly documented, no patch exists, the mitigation must happen now.
No. github.dev workspaces are trusted by default — the workspace-trust dialog does not apply there. Local workspace extensions are installed in trusted workspaces without additional confirmation. The publisher-trust dialog that has appeared since VSCode 1.97 for extensions from new publishers is deliberately bypassed in the exploit path, by having the local workspace extension define a keybinding that passes the skipPublisherTrust option to the install command.
Not directly — the exploit goes through the developer's browser, not the platform infrastructure. Indirectly yes: if a developer with write access to the TYPO3 sitepackage repo or the Sylius plugin repo is compromised, the attacker has the same push access as the developer. In a multi-tenant platform architecture whose deployment pipeline triggers on GitHub tags or branches, that is the direct supply-chain entry point. The mitigation is on the developer side (site-data clearing, awareness), not on the platform side.
A password change alone does not close the gap, because the stolen token is an OAuth session token, not a password derivative. The correct immediate measure is: revoke all active OAuth sessions on GitHub (Settings → Sessions → „Revoke all“), clear github.dev site data in the browser, and then review the list of authorised OAuth apps and personal access tokens for unknown entries. A password change is then a useful supplement if you suspect the attacker read further credentials (e.g. stored secrets in repos) via the stolen token.
The VSCode webview escape is no CVSS heavyweight in the classic sense: no memory error, no authentication bypass, no actively exploited zero-day in the wild. What makes the finding operationally serious is the combination of a trivial entry bar and maximum impact. One click on a link, an OAuth token with full repo access, no patch, a public proof of concept.
For TYPO3 and Sylius platform operators in the German Mittelstand whose platform code lives on private GitHub repos, the mitigation is one browser action per developer plus a team communication for awareness. That is little operational effort, but only effective if it is actually carried out and not dismissed as „doesn't affect us, we rarely use it“. A single developer with a persisted github.dev login and push access to the platform repo is enough as an entry point.
The structural lesson reaches beyond this single bug. The webview boundary in VSCode was designed as a security boundary, and for DOM isolation it works. The break lies in the assumption that forwarded keyboard events have no security relevance. That is the same class of assumption violation we saw with CVE-2026-45793 (Composer token leak): a validation assumption stable for years tips over due to a transparent change in a neighbouring component. In both cases the problem is not the validation itself, but the implicit trust relationship across an API boundary.
The question is not whether Microsoft will patch the webview keydown-forwarding mechanism — that will most likely happen. It is whether your platform developers cleared the site data in the hours and days between full disclosure and patch, or whether the information chain between security awareness and the browser action broke at the same place where VSCode's trust model broke.
![[Translate to English:] Foto von Kai Ole Hartwig.](/fileadmin/_processed_/e/9/csm_ole-neu_73323ad80d.jpeg)
Programming since 2002 – self-taught, set up my own business with KO-Web in 2012. Over 100 projects, with a focus on security, performance, automation and quality. Today freelance: DevSecOps consulting, training and software development.