
Security Research

Golan Myers
|
|
Reading Time:
5
min
TL;DR
When was the last time you audited the extension packs in your organization? Who knows: maybe you’ve been hacked by resurrected extensions.
Extension packs bundle multiple IDE extensions into a one-click install you trust without reviewing each piece. We discovered that Open VSX and the VS Code Marketplace allowed packs to reference non-existent extensions. Attackers could claim those empty slots, publish malicious code under them, and have it installed automatically alongside the trusted pack - silently pushing updates to anyone who installed the pack previously. Because extensions run with full host access, this effectively amounts to RCE delivered under the guise of legitimacy. We call this Extension Resurrection - it affected 750+ packs and 500K+ downloads. Open VSX and Microsoft have both acknowledged and patched the vulnerability following our disclosure.
How Trusted Extensions Become Attack Vectors
The modern endpoint is one of the most dynamic and least governed surfaces in the enterprise. Extensions, packages, plugins, AI tools: assembled daily, rarely reviewed by security, and invisible to EDR.
IDE extensions are a perfect example of how this plays out.
You might ask yourself how prevalent IDE extensions are - well, every developer has at least one installed outside of the default set for their IDE of choice, but that’s not the major story here - in the first 6 months of 2026, VS Code Marketplace has almost doubled itself. The Open VSX and VS Code marketplaces have a combined average of ~1,400 new extensions released every day. AI allows teams to run much faster than before, causing an explosion of new software being released every single day. What makes extensions special?
Developers extend implicit, near-absolute trust to their IDE tooling. When you install an extension pack, you’re not just installing one tool - you’re accepting a curated list of dependencies, all of them granted deep access to your filesystem, your processes, and your network. You reviewed the pack. You didn’t review each extension it pulls in.
That gap - between what a user trusts and what actually gets installed - is exactly where this attack lives.
What started as a routine data quality check uncovered a supply-chain vulnerability spanning two major marketplaces: Extension Resurrection, the ability to silently hijack extensions already referenced inside trusted bundles, by simply claiming a namespace that should never have been left unclaimed.
Extension Packs Explained
Open VSX is an open-source, vendor-neutral marketplace under the Eclipse Foundation umbrella. It exists because Microsoft’s VS Code Marketplace terms explicitly forbid non-Microsoft products from connecting to it - leaving IDEs like VSCodium, Eclipse Theia, Cursor, Windsurf, Kiro and Antigravity without a first-party source. Open VSX fills that gap by providing an alternative to the VS Code Marketplace.
Extension packs are among the most popular features on both Open VSX and the VS Code Marketplace: curated bundles of related tools, installable with a single click. A developer installs a “Python Development” pack and gets a linter, a formatter, a debugger, and a test runner - all at once.

An extension pack and its content on Open VSX
However, this model raises an issue that can occur under two scenarios. The first sits at the intersection of mirroring and bundling. Not every extension was mirrored from VS Code Marketplace to Open VSX. So what happens when a pack is mirrored, but one or more of its bundled extensions are not? The answer: a Shadow Dependency - a dangling reference inside a trusted bundle that points to an extension that simply doesn’t exist on the marketplace. An empty seat at the table. A name without a face. And, as it turns out, a seat that anyone could claim. The second issue is simply the deletion of an existing extension that is referenced by an existing pack.
The Issue: Bringing an extension back to life
First, we must understand what identifies an extension in each marketplace. VS Code Marketplace uses a format of <publisher>.<extension_id>; Open VSX uses <namespace>.<extension_id>. The two essentially use the same concept: a combination of who published (publisher/namespace) and what they published (extension_id). As such, taking over a removed extension requires more than just the ability to register its ID - it requires the ability to register it under the original publisher/namespace.
We pointed our scanner at Open VSX and mapped every extension pack against the actual existence of its bundled extensions. The results were stark: 94 of 321 extension packs contained at least one shadow dependency, and critically, the namespace for that extension was not registered. In the VS Code marketplace, 677 of 4179 extension packs contained at least one shadow dependency, 60 of which belonged to a non-registered publisher.
That’s an open door. Registering a namespace on Open VSX or a publisher on VS Code Marketplace is trivial. So we picked two examples to test the hypothesis:
Open VSX: the
prettify-jsonextension within themohsen1namespace, bundled by a pre-existing pack but absent from the Open VSX marketplace.VS Code Marketplace: the
control-snippetsby thesvipaspublisher, bundled by a pre-existing pack but absent from the VS Code Marketplace.
We attempted to create them with the identical latest versions that we identified - matching metadata, matching ID.
Focusing on Open VSX, the marketplace rejected it.

Open VSX rejected an exact version match, but the error revealed something important: it already “knows” about this extension
The rejection message was illuminating. The marketplace had an internal pointer to the extension - a ghost record from the mirrored pack’s manifest - even though the extension itself had never been published. It was refusing the exact version because it already existed in its index as a phantom reference.
The workaround was trivial: increment the version number.
Extension packs, by design, do not pin to specific versions of their bundled extensions. They reference by ID only. Part of the sell of extension packs is centralized management of a bundle of extensions; requiring individual updates wouldn’t make sense for the stated purpose. So a newer version of the extension would satisfy the pack’s dependency just as well as the original. We published with a bumped version. The extension appeared. The pack’s bundled extension link almost immediately resolved - to our newly uploaded extension.

After registering the namespace and publishing a newer version, the extension is published, and the pack’s bundled extension is resolved to an extension under our control
When a user installs the original, trusted extension pack through Open VSX, our extension installs alongside it. No separate prompt. No additional click. The bundle delivers it silently as part of its curated set.
For developers who already had the pack installed, the exposure window extended further: because extension packs, by design, lack version pinning for their bundled extensions, the auto-update configurations for extensions within them are inherited from the pack’s configuration. The default configuration sets auto-updates as enabled. A user who installed the pack weeks, months, or even years ago under the default settings could pull in the malicious extension on their next IDE update cycle - without ever revisiting the marketplace.
Root Cause
This wasn’t a single oversight. Two independent gaps converged to make the attack viable:
- No enforcement on extension existence at pack creation: Marketplaces accepted extension packs that referenced non-existing bundled extensions. A pack could be published - and mirrored - pointing to extensions that had never been created. This is the root cause. The dependency check that should have blocked it simply wasn’t there.
- Open namespace registration: Namespaces on the affected marketplaces were freely registerable, regardless of whether or not they were referenced by existing software. The attacker does not need to compromise an existing account - they simply claim an unclaimed one and publish into it.
On Open VSX, the attack surface extended beyond extension packs. During triage, it was discovered that extension dependencies - extensions that declare other extensions as dependencies in their manifests - are subject to the identical vulnerability.
The Impact: 0-Click RCE Delivered Through Legitimacy
VS Code extensions - and extensions for compatible IDEs like Cursor, Kiro, Windsurf, Antigravity, VSCodium, and Eclipse Theia - run with Node.js host access. They can read and write files, spawn child processes, and make outbound network requests. An extension is not sandboxed in any meaningful sense from the perspective of code execution.
Installing a malicious extension is, functionally, remote code execution on the developer’s machine.
This attack delivers the malicious payload without the victim ever choosing the extension. They chose a trusted bundle. The bundle chose the malicious payload for them. Auto-update primitives made it worse tenfold.
The aggregated download count across the vulnerable packs on Open VSX and the VS Code Marketplace reached over half a million downloads. The targets are almost exclusively software developers - high-value individuals with access to source code repositories, cloud credentials, deployment pipelines, and internal tooling. Assuming a (very) conservative half of them had auto-update enabled, that’s a quarter of a million compromised developer endpoints guaranteed in under 24 hours.
Responsible Disclosure
Eclipse Foundation / Open VSX - February 5, 2026
We reported the vulnerability to the Open VSX team at the Eclipse Foundation on February 5, 2026. Their response was immediate and professional. The team assigned all at-risk namespaces to the open-vsx account to prevent malicious registration - blocking the attack vector in hours, not weeks. The team committed to disabling the creation of extension packs with non-existent bundled extensions, and similarly for extensions with non-existent extension dependencies. The pre-publication check has since been implemented and is now enforced. Our experience with the Eclipse Foundation team was very positive.
Microsoft (MSRC) - February 17, 2026
We reported the issue to Microsoft via MSRC on February 17, 2026, accompanied by a full proof-of-concept and video demonstration. The initial response assessed the issue as Moderate severity as follows: “After careful investigation, this case has been assessed as Moderate severity and does not meet Microsoft’s bar for immediate servicing as Visual Studio Marketplace has existing publisher resurrection prevention…”. As this was not the case, we pushed back, pointing to the video evidence and additional evidence of re-registering removed publishers. Microsoft reopened the case. After further internal investigation with the engineering team, they responded:
The fix - preventing namespace resurrection for extensions previously present in bundles - was released in two stages: admin actions in October 2025, user actions in May 2026. Details of the fix are documented in the VS Marketplace public discussion: github.com/microsoft/vsmarketplace/discussions/1708.
Microsoft acknowledged that the completion of the fix (covering user actions) occurred after this report was submitted, and added me to their public security researcher acknowledgement page (with no data regarding why I was added and no mention of this issue). It is worth noting that the period between the partial fix (October 2025) and the complete fix (May 2026) left real exposure for user-action resurrection events, as we demonstrated.
Strategic Implications
For Organizations and Security Teams
Developer workstations are high-value targets, and IDE extensions are one of the least-audited attack surfaces in the enterprise. Extension packs compound the risk: one install decision silently expands the attack surface by five, ten, or more extensions, none of which the user explicitly reviewed. Treat extension packs in the same threat model as direct extension installs - and review the bundle manifest, not just the pack name.
Security teams must have visibility and capabilities of the following:
Installed extensions - which extensions and packs are installed within the organization
IDE Configurations - is auto-update enabled, and if so, for which extensions. Are organizational policies in place to limit extensions to a pre-approved list?
Extension scanning - auditing the capabilities, security posture and dangers posed by each installed extension. This is a continuous process, for every new version.
Extensions are one example of a much larger gap. The endpoint attack surface expands constantly: new installs, updates, configurations, and AI tools pulling in new dependencies daily. Everything running on it needs to be continuously known, vetted, and governed. Not as a one-time audit. As an ongoing process that scales across every endpoint in the organization.
For Marketplace Operators
Two checks would have prevented this entirely: validate that all bundled extensions and declared dependencies exist at pack submission time, and protect namespaces referenced in existing published packs from open registration. Phantom pointers in a package index are not a data quality problem - they are an attack surface. The Open VSX team addressed both points decisively; they serve as a model for how a marketplace can respond.
For Developers
Auto-updated extension packs behave like auto-updates for every extension they bundle. If you’re not on a pinned, audited extension list managed by your organization, be aware that “install once” does not mean “static forever.” Periodically review what your IDE has actually installed - not just what you chose to install.
Conclusion
Supply chain attacks don’t always require compromising a build server, poisoning a registry, or social-engineering a maintainer. Sometimes the vulnerability is structural: a gap between what a system references and what it protects, left open long enough for anyone to walk through.
This is a reminder that the most dangerous dependencies are the ones nobody notices - the phantom entries in a bundle manifest, pointing at names that exist only in the index, until they don’t.
Organizations that lack the visibility and control over what is installed, how it is configured, and how the update flow works are a few clicks away from an incident.
Script to detect the packs on your own endpoint: https://github.com/bloom-security/extension-resurrection
To see how Bloom could help you with detection, prevention and response, schedule a demo here