DEV Community

Cover image for A clone of our VS Code extension appeared on OpenVSX five days before we open-sourced the repo. It has 5,090 downloads and is using our GitHub OAuth app.
psychomafia.tiger
psychomafia.tiger

Posted on

A clone of our VS Code extension appeared on OpenVSX five days before we open-sourced the repo. It has 5,090 downloads and is using our GitHub OAuth app.

Names (fyltroven, Mapkoforceps) are used because they are public on OpenVSX and GitHub. We are not claiming intent. Our OpenVSX takedown report is open as of writing.

We did not expect to find this

We flipped the repo public yesterday. April 21, 10:29 UTC. A private repo the day before, an MIT license the day after, that kind of week.

This morning we checked our OpenVSX listing and our extension was there twice.

Ours: gitchat.gitchat, 11,308 downloads, verified: true. Published yesterday.

The other one: fyltroven.gitchat-fast-tool. 5,090 downloads. unrelatedPublisher: true. Published April 16.

Five days before we open-sourced. Our repository was still private on April 16. Nobody outside the team had the source. The clone was already live.

We pulled its package.json expecting a half-thorough rebrand. name, publisher, homepage, bugs, repository were all updated. One field was not. And the further we dug into the shipped bytes, the less the interesting question was how someone rebranded our code, and the more it became how they had our code at all.

OpenVSX listing for fyltroven.gitchat-fast-tool showing orange unrelatedPublisher warning banner and 5,090 downloads
The fake listing on OpenVSX. Orange banner at top is OpenVSX's own unrelatedPublisher: true flag.

Side by side

Ours The clone
Namespace gitchat.gitchat fyltroven.gitchat-fast-tool
Publisher verified true false
OpenVSX flag normal unrelatedPublisher: true
OpenVSX downloads 11,308 5,090
Version 1.1.5 1.0.5
License MIT MIT
Published 2026-04-21 10:29 UTC 2026-04-16 15:29 UTC

Both listings are public. Open either URL and you see what we saw.

The field they forgot

The clone's package.json from the OpenVSX CDN:

GET https://open-vsx.org/api/fyltroven/gitchat-fast-tool/1.0.5/file/package.json
Enter fullscreen mode Exit fullscreen mode
{
  "name": "gitchat-fast-tool",
  "publisher": "fyltroven",
  "repository": {
    "url": "https://github.com/Mapkoforceps/gitchat-fast-tool.git"
  },
  "homepage": "https://github.com/Mapkoforceps/gitchat-fast-tool#readme",
  "bugs": {
    "url": "https://github.com/Mapkoforceps/gitchat-fast-tool/issues"
  },
  "qna": "https://github.com/GitchatSH/gitchat_extension/issues"
}
Enter fullscreen mode Exit fullscreen mode

Fake package.json with qna URL highlighted in red, still pointing to GitchatSH/gitchat_extension
Every other metadata field got rebranded. qna was left pointing at our repo.

The qna URL points to our repository, the one we made public yesterday. Everything else is rebranded. This one they missed.

At that point it was a copy, not a coincidence. The question was how deep.

Seven minutes

GitHub's REST API for the clone's repo:

repo: Mapkoforceps/gitchat-fast-tool
  created_at: 2026-04-16T15:22:16Z
  pushed_at:  2026-04-16T15:24:58Z
Enter fullscreen mode Exit fullscreen mode

OpenVSX for the listing:

timestamp: 2026-04-16T15:29:02Z
Enter fullscreen mode Exit fullscreen mode

Repo created 15:22. First push 15:24. Published to OpenVSX 15:29. Seven minutes total. Nobody writes a Socket.IO chat extension with a sidebar webview in seven minutes. The only thing you can do in that window is upload code you already had.

GitHub commits page for Mapkoforceps/gitchat-fast-tool showing commits within minutes of repo creation
Commit history on the clone's repo. Initial commit at 15:22, push at 15:24, OpenVSX publish at 15:29.

And our source was still private on April 16. It stayed private for five more days.

The part we cannot explain

The repository was on GitHub with visibility private until April 21 at 10:29 UTC. The clone was already on OpenVSX on April 16 at 15:29 UTC. Between those two timestamps, someone had our code on their laptop, packaged, and live.

We do not know how.

What we have checked so far:

  • GitHub access logs for the repo show only authorized team members.
  • There is no mirror of the source, no CI artifact we accidentally made public, no leaked log that we have found.
  • The project was not invisible before we shipped. We posted in r/vscode this week describing what we were building. Anyone reading that thread would have known the project existed and roughly what it did. The thread did not include a source archive or a binary.

That r/vscode thread predates the clone. If you find it and check the timestamps you can draw your own line between points. We are not going to draw it for you, because we do not know the real answer and guessing in print would be unfair to whoever did or did not do this.

What we can say is narrow. Our repo was private when the clone appeared. The clone's publisher had a packaged copy of our extension five days before the code was public. If anyone reading this has seen a pattern like it, on OpenVSX or anywhere else, we would like to hear about it.

Inside the .vsix

OpenVSX lets anyone download the packaged extension. We pulled the clone's .vsix (8.75 MB) and unzipped it.

Brand assets:

gitchat_banner.png
gitchat_hook_cover.gif
gitchat_myrepo.png
gitchat_social_cover.png
gitchat_top people.png
gitchat_toprepo.png
feature-chat.png
feature-explore.png
feature-friends.png
feature-profile.png
Enter fullscreen mode Exit fullscreen mode

Terminal output of ls -lh on unzipped clone .vsix showing gitchat_banner.png, gitchat_toprepo.png, feature-chat.png and other branded files
Unzipped .vsix folder. Filenames carry our brand prefix unchanged.

These are our image files, filename prefix and all. The clone did not rename them.

The minified JS bundle (dist/extension.js, 484 KB) was not rebuilt. strings on it:

{id:"gitchat.signIn",handler:...}
{id:"gitchat.messageUser",handler:...}
{id:"gitchat.viewMyProfile",handler:...}
"Sign in to view your GitChat profile."
"Enter GitHub username to message"
Enter fullscreen mode Exit fullscreen mode

The package.json registers 15 command IDs under gitchat.* (gitchat.signIn, gitchat.signOut, gitchat.userMenu, etc). There is no reason for an extension called gitchat-fast-tool under publisher fyltroven to be registering commands in our namespace, other than that is what was on disk when they ran vsce package.

The .vsix also shipped a .claude/settings.json with a PreToolUse hook for docs/contributors/${USERNAME}.md. That is our internal contributor-doc workflow. You do not ship somebody else's Claude Code config file by accident.

It gets worse: the clone uses our backend

At this point we thought we were looking at an IP issue. Then we opened the contributes.configuration.properties block of the shipped package.json:

{
  "gitchat.apiUrl": {
    "default": "https://api-dev.gitchat.sh/api/v1"
  },
  "gitchat.wsUrl": {
    "default": "https://ws-dev.gitchat.sh"
  },
  "gitchat.githubClientId": {
    "default": "Ov23liXf7KFWwKzcOHE0",
    "description": "GitHub OAuth App Client ID for device flow authentication"
  }
}
Enter fullscreen mode Exit fullscreen mode

Those are our servers. That client ID is the OAuth app we built and registered under our team's GitHub account.

Diagram of OAuth device flow: 5,090 users install the clone, authenticate via our OAuth app, traffic routes through our backend to our database
What happens when a user signs into the clone. Every arrow ends on our infrastructure.

Reading the rest of the bundle, what happens to a user who installs the clone:

  1. They install fyltroven.gitchat-fast-tool from OpenVSX.
  2. They hit Sign In. The extension starts a GitHub device flow using our client ID.
  3. GitHub shows them a device-code screen for the OAuth app registered under our team. They grant permissions to that app.
  4. Their VS Code gets a token issued against our OAuth app.
  5. The extension calls api-dev.gitchat.sh and opens a socket to ws-dev.gitchat.sh. Our backend validates the token and creates or looks up the user record in our database.
  6. "GitChat Fast Tool" shows up in their sidebar. Every message they send lives on our servers under a token issued by our app.

We did not sign off on any of this. We found out because we downloaded the .vsix.

One honest caveat. GitHub's OAuth device flow does have a known public-client-ID-impersonation issue (Praetorian writes about it). In our specific case the device flow is doing what it is specified to do, tokens are scoped by what the user clicks through, and the backend is ours so nothing exfiltrates past us. The awkward fact is that 5,090 people installed an extension from an unverified publisher, and that extension has been quietly running through our OAuth app and our database the whole time. Neither we nor they knew.

Where did 5,090 installs come from

Google   "gitchat-fast-tool"       : no matches outside the listing
Reddit   search                    : no results
Twitter  search                    : no results
GitHub   repo stars                : 0
Blog posts, social media promotion : none found
Enter fullscreen mode Exit fullscreen mode

5,090 installs with zero discoverable source. We do not have an answer. We are not calling anyone an install farm. We just cannot make 5,090 and zero line up.

If you have seen this on OpenVSX before, or you know of anyone running detection on install-count anomalies for VS Code marketplaces, talk to us.

The publisher

login:       Mapkoforceps
name:        null
bio:         null
email:       null
blog:        (empty)
location:    null
company:     null
followers:   0
created:     2026-03-13T11:46:50Z
public_repos: 2
Enter fullscreen mode Exit fullscreen mode

GitHub profile page for Mapkoforceps: no avatar, no bio, 0 followers, 2 public repositories
The GitHub profile that published the clone. Created 34 days before the publish, no profile info, no followers.

Two repos on that account. oogymera, created the same day the account was, empty, zero stars. gitchat-fast-tool, the clone.

This is a thin profile by any standard. We are not attributing intent. We noticed the same signals that you probably noticed reading that block, and they are the reason we decided a cease-and-desist email would not go anywhere useful.

What we did

  1. Filed an OpenVSX takedown on the open-vsx.org issue tracker, citing the unrelatedPublisher flag, the qna URL mismatch, the identical minified bundle, and the backend config.
  2. Flipped our repo public on MIT at github.com/GitchatSH/gitchat_extension (the evidence chain is in the commit history, so we wanted that public regardless).
  3. Started planning the OAuth client ID rotation and the user-migration that goes with it.

No email to the clone publisher. The profile above is why.

What we are asking

Three questions, picked because they are things we genuinely do not know the answer to.

One. Our repo was private on April 16. How does a clone of a private repo show up on OpenVSX? If you have seen a clone appear before the source went public, we would like to hear it.

Two. 5,090 downloads and zero footprint. If this shape is familiar to anyone, tell us what you think happened and how you would check.

Three. If you ship an open-source VS Code extension with a backend, your config defaults become part of a public surface you cannot take back. We knew that about our own release. We did not expect the defaults to be absorbed by a rebranded listing with five thousand downloads, five days before we shipped the source. If you have seen config-inheritance like this in a cloned extension, share the details.

We are the GitChat team. Our real extension is gitchat.gitchat on OpenVSX and GitchatSH.gitchat on the VS Code Marketplace. Source at github.com/GitchatSH/gitchat_extension on MIT. Comments are on.

Top comments (0)