Is VPN для ChatGPT safe?

High risk

VPN для ChatGPT is high risk. Opening the popup fetches a config file from GitHub Pages, then Blogspot, then Google Docs as fallbacks, ROT-3 shifted and parsed as JSON. A 'u' value replaces the API host; an 's' value replaces the proxy list.

sherechevskiyv5.5Chrome Web Store
72Risk
Who publishes it

sherechevskiy - 17 other listings from the same operator, 10 of them carrying a finding

What this publisher told the store about itself, and the other listings that told it the same thing.

Publisher
sherechevskiy

Shared hosts - 3 hostnames

Hostnames hardcoded in this extension that few other listings call. That can mean one operator behind both, and it can equally mean a small shared vendor, so it is context rather than a conclusion. Hosts that many listings call are left out: they are services, not connections.

api.hhos.ru
Also called by 2 other listings: ВПН для ЧатГПТ / ChatGPT, ВПН для Gemini / VPN for Gemini
dtxtension.blogspot.com
Also called by 2 other listings: ВПН для ЧатГПТ / ChatGPT, ВПН для Gemini / VPN for Gemini
s-extension.github.io
Also called by 2 other listings: ВПН для ЧатГПТ / ChatGPT, ВПН для Gemini / VPN for Gemini

AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.

Publishers can request a review.

Findings

Backend API and proxy list pulled from GitHub Pages and overwritten at runtime

HighunwantedCWE-829Dynamic sandbox

Opening the popup fetches a config file from GitHub Pages, then Blogspot, then Google Docs as fallbacks, ROT-3 shifted and parsed as JSON.

What actually happens

You did this

You open the extension popup.

The extension did this

The extension fetches a config file from an external GitHub Pages page (Blogspot/Google Docs fallbacks), decodes it, and overwrites its backend API host and proxy list.

The new backend host is written to local storage, so it persists across sessions until changed again by a later fetch.

Captured request

GEThttps://s-extension.github.io/DataExst/data.json

Observed during dynamic analysis when the popup opened: a ~4.6 KB response body, ROT-3 encoded. After decoding, it contained a backend host override and roughly 65 proxy server entries that were not present in the extension's shipped js/conf.js.

Why you can't catch this in DevTools

The fetched config is shifted with a ROT-3 letter cipher before it is published, so the raw response is not directly readable. Shifting each letter back by three positions reveals normal JSON naming a backend host and proxy entries.

Decoded value
{"u":"obratx.shop", "s":[ /* ~65 base64-encoded proxy entries; each decodes to host:port:user:pass|expiry|country|tag, e.g. 168.81.75.126:9091:tFC47N:BDpmJp|2026-07-14|in|rmd */ ]}

The code that does this

The fetch-decode-override path, from the shipped source.

Readable version

What the decode-and-override logic does

// On popup open: fetch the remote config, decode it, apply overrides.function applyRemoteConfig(rawBody) {  const json = JSON.parse(rot3Decode(rawBody.trim()));   // showx(body, 3)  if (json.u && json.u.length > 0) {    backendApi = 'https://' + json.u;                    // overwrite api.hhos.ru    chrome.storage.local.set({ apiurl: json.u });        // persist across sessions  }  if (json.s) {    chrome.storage.local.set({ servers: JSON.stringify(json.s) }); // replace proxy list    rebuildServerList(json.s);  }}

Hosts involved in remote config delivery and the resulting backend

    • s-extension.github.io

    Primary config source. Serves DataExst/data.json (ROT-3 encoded) used to override the backend host and proxy list. Hosted on GitHub Pages.

    • dtxtension.blogspot.com

    Fallback config source. Config read from a .post-body paragraph on the page. Hosted on Google Blogspot.

    • docs.google.com

    Fallback config source. Config read from a DOCS_modelChunk script block in a Google Docs document.

    • api.hhos.ru

    Default bundled backend host, used until a fetched config supplies a 'u' value that replaces it.

Reproduce it yourself

Fetches the extension's remote config from GitHub Pages, applies the ROT-3 decode the extension uses, and prints the backend host override ('u') and proxy entries ('s'). Lets you confirm what the external file currently instructs the extension to do.

Requires
  • Node.js 18+ (global fetch)
decode-remote-config.js · js
// decode-remote-config.js// Usage: node decode-remote-config.jsconst URL = 'https://s-extension.github.io/DataExst/data.json';function rot3(text) {  return text.split('').map(ch => {    if (/[a-z]/i.test(ch)) {      const code = ch.charCodeAt(0);      const base = code >= 65 && code <= 90 ? 65 : 97;      return String.fromCharCode(((code - base - 3 + 26) % 26) + base);    }    return ch;  }).join('');}(async () => {  const raw = await (await fetch(URL)).text();  const json = JSON.parse(rot3(raw.trim()));  if (json.u) console.log('Backend host override (u):', 'https://' + json.u);  if (Array.isArray(json.s)) {    console.log(`Proxy entries (s): ${json.s.length}`);    for (const e of json.s.slice(0, 5)) {      console.log('  ', Buffer.from(e, 'base64').toString('utf8'));    }  }})();
How to run it
  1. 1Save this file.
  2. 2Run: node decode-remote-config.js.
  3. 3Read the printed backend host override and the first few decoded proxy entries. Re-run later to see whether the externally-hosted config has changed.
Updated 22 October 2026mcbbkppinglngggemoflhaajipkapgml