astropod get started contact sales sign in

77 Counterfeit Open VSX Extensions, with a Config File That Keeps Installing The

Published on gastropod.io on 08-05-2026

77 Counterfeit Open VSX Extensions, with a Config File That Keeps Installing Them


Tags: software supply chain security, vulnerability intelligence, ide-extensions, open-vsx, ci-cd-security, credential-theft, devcontainers


Between July 26 and August 1, someone published 77 extensions to Open VSX, each copying the name, namespace, and description of a real VS Code Marketplace extension, usually with a version # 0.0.1, and from non-associated accounts that have no connection to the original authors. Manifold Security identified the set and Open VSX removed all 77 on August 3. The squatted namespaces include AMD, LEGO Education, Hyperledger, Azure, Salesforce OSS, IOTA, a .gov agency, and marketplace.visualstudio, which impersonates the marketplace itself.

Each package included a call-home/beacon function in place of the bundled extension.js. The beacon functions sent small (1.6 to 3.3 KB) packets of information that included the hostname plus sometimes the workspace folder name or editor version and it also would send larger packets of information out (about 10 KB) that collected a full reconnaissance profile: hostname, OS username, editor name and version and machine ID, platform, architecture, locale, timezone, and the full filesystem path of the open workspace. They read .git/config for the origin and upstream remote hosts and organizations and the domain of the configured commit email, read .git/HEAD for the branch and commit SHA, enumerate up to sixty installed extension IDs, and collect GITHUB_REPOSITORY, CI_PROJECT_PATH, the Azure DevOps collection URI, the Buildkite organization slug, the CircleCI project username, the Codespace name, and the Gitpod workspace context URL. On a build runner, that last group is the private repository path.

The Open VSX listings documented most of this under a heading called Telemetry, and Manifold Security's writeup confirms that the collection infrastructure is designed for persistence. mangorbit[.]com was registered on July 15, eleven days before the first package appeared, on a three-year term through a registrar that redacts registrant details. The retry schedule runs at roughly fifteen minutes, fifty minutes, three and a half hours, then every seven or eight hours, resuming on every editor restart and giving up only after seven days. The code accepts any HTTP response as success, including an error status, because it only needs the request to arrive. If every endpoint fails, it queries a DNS TXT record at _beacon.<domain> for a replacement base URL, which lets the operator relocate collection over a channel most egress filtering would ignore.

The reconnaissance payload also checks whether the open workspace's devcontainer.json or .vscode/extensions.json references the extension's own ID, and reports the answer as a flag. The threat actors that deployed this were measuring how many installs came from repository configuration rather than from a person clicking install. Any image, machine, or workspace config that already pinned one of these names still has the code, and the beacon still runs on every editor start.

Two registries with one namespace are what makes this work. Open VSX and the VS Code Marketplace maintain separate ownership and verification rules, so a name that is unambiguously owned on one can be unclaimed on the other, and anything resolving that name has no way to tell which registry answered. Devcontainer builds resolve extension names on every container build. Provisioning scripts resolve them on every image bake. Coding agents resolve them from whatever name appeared in a document. I covered a very similar agent version of this failure in FakeGit, where 7,600 repositories existed to be found by name.

Gastropod does not proxy Open VSX. What it does cover is the artifact these extensions arrive inside on a build fleet: the container image. A devcontainer base is an OCI artifact, and Gastropod records the sha256 of every image pulled through it and attributes each pull to a principal with a timestamp and a client. So "which of our build images were rebuilt between July 26 and August 3, and which runners pulled the results" is a query against the audit spine with a definite answer, rather than a survey of every runner in the fleet. The dependent graph then gives you the services built on those images, and each has a CycloneDX SBOM you can hand to whoever is checking .devcontainer configs against Manifold's package list.

The registry cannot tell you what an extension does at runtime. It can tell you exactly which image digests carried it and who consumed them, which is the part that can take a lot of time to reconstruct by hand. If that reconstruction is currently a spreadsheet exercise at your shop, point one build pipeline at Gastropod and check the audit log after a week.

← news