Is ЮБуст - VPN для YouTube. Обход блокировки Ютуб без ВПН. VPN для браузера safe?

Medium risk

ЮБуст is medium risk. ЮБуст ships a hardcoded GA ID (G-XCPV2XK66M) and API secret, logging installs, signups, rival extensions found, and other events. Two permanent UUIDs, made on first run, tag every event, tracking one install across restarts.…

Uboostv8.11.16Chrome Web Store
45Risk
Who publishes it

IP Zamolotskikh - no other listings under this identity, 4 shared hostnames

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

Publisher
Uboost
Declared legal entity
IP Zamolotskikh
Registered address
Bogenbai Batyr Street 86, Almaty, Алматы 050000, KZ
Registered contact
Uboost

Shared hosts - 4 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.

uboost.space
Also called by 3 other listings: Врубель, Открывашка, перемен-vpn-с-российским
ubst.space
Also called by 3 other listings: Врубель, Открывашка, перемен-vpn-с-российским
naruzhu.click
Also called by 4 other listings
staticfiles.cukubst.top
Also called by 4 other listings

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

Publishers can request a review.

Findings

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-359
SourceAI SANDBOX

Telemetry to Google Analytics with hardcoded credentials and persistent IDs

ЮБуст ships a hardcoded GA ID (G-XCPV2XK66M) and API secret, logging installs, signups, rival extensions found, and other events.

Two permanent UUIDs, made on first run, tag every event, tracking one install across restarts.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You install ЮБуст or finish onboarding to create your free-trial account.

Same path fires on every browser restart for session events, on every detected conflict with another VPN/ad-blocker extension, and on every uncaught error in the service worker.

The extension did this

ЮБуст posts a JSON event to GA tagged with two permanent per-install IDs, using an API secret hardcoded in the extension.

The same event pipeline carries 'install', 'user_created', 'manual_start', 'video_redirect', 'proxy_controlled_by_other_extension', 'vpn_extension_conflict', 'ad_blocker_conflict', and other lifecycle/observability events, each one stitched to the same persistent client_id.

02EvidenceNETWORK CAPTURE
Captured request
POSThttps://www.google-analytics.com/mp/collect?measurement_id=G-XCPV2XK66M&api_secret=<redacted>
204 No Content, Google Analytics confirms event accepted. Four such POSTs were observed during dynamic analysis for events 'install' and 'user_created'.
Headers
Originchrome-extension://jddgbeighonaipjikdnfdpiefhoomlae
Content-Typetext/plain;charset=UTF-8
Body
{
  "client_id": "c4aacd99-66ff-46ba-8dba-72e5c45176e7",
  "events": [
    {
      "name": "user_action",
      "params": {
        "action": "install",
        "category": "extension",
        "session_id": "1776464941481",
        "engagement_time_msec": 100
      }
    }
  ]
}
03EvidenceFIELD TABLE
What ends up in the developer's Google Analytics dashboard for your install:
FieldValueWhy it matters
Your permanent client ID
c4aacd99-66ff-46ba-8dba-72e5c45176e7A random UUID made on first run, stored forever. Every event carries it, letting the developer stitch your history across sessions.
Your permanent device ID
304bd233-9b22-4f7c-bebc-e9fb1173a3cfA second UUID kept in storage and a first-party cookie. Clearing storage doesn't remove it; the cookie repopulates it.
Session ID
1776464941481Groups the events from one browsing session together. Resets after 30 minutes of inactivity.
Event name
user_action / installReported action: install, user_created, page_view, manual_start, video_redirect, extension-conflict types, extension_error.
Conflicting extension ID + name
cjpalhdlnbpafiamejdnhcphjbkeiagm / uBlock OriginIf another VPN, proxy, or ad blocker is installed, ЮБуст names it and its store ID, so the developer learns which privacy tools you run.
YouTube tab URL (on video_redirect)
https://www.youtube.com/watch?v=dQw4w9WgXcQWhen the extension intercepts a video to redirect it through its proxy, the YouTube URL of that tab is sent as the event label.
Extension version
8.10.3Which build of ЮБуст is installed.
Error message + type
Failed to fetch / user_creation_failedAny internal error is sent as an 'extension_error' GA event, and also to the developer's own Sentry server.
04EvidenceCODE COMPARE
The code that does this

The shipped tracker class, with credentials baked in

What it actually does
GoogleAnalyticsTracker — annotated
const Tracker = new class GoogleAnalyticsTracker {
  // Reads the persistent UUID from chrome.storage.local under StorageKeys.ClientId.
  // If missing, mints a new UUID and saves it. Result: a per-install ID that
  // survives forever (until the user explicitly clears the extension's storage).
  async getOrCreateClientId() {
    const { clientId } = await Storage.get(StorageKeys.ClientId);
    if (typeof clientId === 'string') return clientId;
    const fresh = self.crypto.randomUUID();
    await Storage.set({ [StorageKeys.ClientId]: fresh });
    return fresh;
  }

  // Standard GA4 30-minute rolling session window.
  async getOrCreateSessionId() {
    const { sessionData } = await Storage.get(StorageKeys.SessionData);
    let session = sessionData ? { ...sessionData } : null;
    const now = Date.now();
    if (session) {
      if ((now - session.timestamp) / 60000 > 30) session = null;
      else { session.timestamp = now; await Storage.set({ sessionData: session }); }
    }
    if (!session) {
      session = { session_id: now.toString(), timestamp: now };
      await Storage.set({ sessionData: session });
    }
    return session.session_id;
  }

  // Builds a GA4 Measurement Protocol payload and POSTs it to Google.
  // The measurement_id and api_secret are HARDCODED in the URL — anyone
  // who unzips the extension can read them; conversely, every install of
  // ЮБуст is reporting against the same GA property keyed on client_id.
  async sendEvent({ name, params }) {
    try {
      const [client_id, session_id] = await Promise.all([
        this.getOrCreateClientId(),
        this.getOrCreateSessionId(),
      ]);
      const body = {
        client_id,
        events: [{
          name,
          params: { ...params, session_id, engagement_time_msec: 100 },
        }],
      };
      const url = 'https://www.google-analytics.com/mp/collect'
        + '?measurement_id=G-XCPV2XK66M'
        + '&api_secret=<redacted>';
      const resp = await fetch(url, { method: 'POST', body: JSON.stringify(body) });
      if (!resp.ok) console.error('Failed to send GA event:', await resp.text());
    } catch (e) { console.error('Error sending GA event:', e); }
  }

  trackPageView(page) {
    return this.sendEvent({
      name: 'page_view',
      params: { page_title: page, page_location: chrome.runtime.getURL(page) },
    });
  }

  trackUserAction(action, category, label) {
    return this.sendEvent({
      name: 'user_action',
      params: { action, category, label },
    });
  }

  trackError(error_message, error_type) {
    return this.sendEvent({
      name: 'extension_error',
      params: { error_message, error_type },
    });
  }
};
Conflict-extension reporters — annotated
// Whenever ЮБуст walks chrome.management to look for other VPN / proxy /
// ad-blocker / 'internal' extensions, it reports each conflict to GA along
// with the OTHER extension's Chrome Web Store ID and human-readable name.
// Result: the developer's GA dashboard tells them which competing privacy
// tools each one of their users has installed.
if (proxyConflict.hasConflictingExtension) {
  Tracker.trackUserAction(
    'proxy_controlled_by_other_extension',
    proxyConflict.conflictingExtensionName ?? 'unknown',  // e.g. 'AdBlock Plus'
    proxyConflict.conflictingExtensionId,                  // e.g. 'cfhdojbkjhnklbpkdaibdccddilifddb'
  );
}
// Same shape for internal_extension_conflict, vpn_extension_conflict,
// ad_blocker_conflict.

// Onboarding / lifecycle:
await Tracker.trackUserAction('install',      'extension');                       // first install
await Tracker.trackUserAction('update',       'extension', previousVersion);      // version bump
await Tracker.trackUserAction('user_created', 'premium');                          // premium signup
await Tracker.trackUserAction('manual_start', 'proxy');                            // proxy started

// YouTube video routing — the YouTube URL is forwarded as the GA event label.
await Tracker.trackUserAction('video_redirect', 'youtube', youtubeUrl);
05EvidenceSTORAGE DUMP
What's stored on your device

clientId feeds GA; deviceId feeds the dev's backend. Both mint once, never cleared; deviceId is also a cookie, surviving storage clears.

Locationchrome.storage.local, keys 'clientId', 'deviceId', 'sessionData' (and a sibling first-party cookie 'deviceId' on the developer's cookieDomain)
Contents (JSON)
{
  "clientId": "e316df7b-1d92-4aa0-b66d-eed03fe588c7",
  "deviceId": "304bd233-9b22-4f7c-bebc-e9fb1173a3cf",
  "sessionData": {
    "timestamp": 1776464941481,
    "session_id": "1776464941481"
  }
}
06EvidenceTHIRD PARTY LIST
Where each piece of telemetry ends up:
  • www.google-analytics.com

    Receives every Measurement Protocol POST: installs, signups, conflict reports, video redirects, errors. Under GA4 property G-XCPV2XK66M.

  • sentry-ws-1.vpnn.space

    Self-hosted Sentry owned by the same developer. Receives exceptions, rejections, and arbitrary extras. Tagged extension_code='youboost' (service_worker.js line 1947).

  • uboost.space / ubst.space

    The developer's backend. Receives the deviceId UUID on trial, signup, and update checks, plus the same UUID as a cookie, re-identifying your install if storage is cleared.

07EvidenceARTIFACT
Reproduce it yourself

Run this in the ЮБуст service worker's DevTools console to intercept every Google Analytics POST the extension makes and print the full URL (with hardcoded creds), the JSON body, and the resolved client_id/session_id/event params. Confirms the hardcoded credentials and persistent IDs without needing a network proxy.

RequiresChrome with Developer mode enabledЮБуст installed and onboarded (so chrome.storage.local has clientId/deviceId)
uboost-ga-decoder.js · js
// uboost-ga-decoder.js
// Drop into the ЮБуст service worker DevTools console:
//   chrome://extensions → enable Developer mode → click the
//   'service worker' link under ЮБуст → paste below.
//
// Wraps fetch() so every google-analytics.com/mp/collect call is
// dumped in full BEFORE it hits the wire. Also dumps the persistent
// IDs from chrome.storage.local on load.

(async () => {
  // 1. Show the persistent IDs the extension is using to tag your install.
  const keys = await chrome.storage.local.get(['clientId', 'deviceId', 'sessionData']);
  console.log('[YOUBOOST_IDS] persistent identifiers in chrome.storage.local:');
  console.table(keys);

  // 2. Hook fetch to capture every GA Measurement Protocol POST.
  const origFetch = self.fetch.bind(self);
  self.fetch = async function (input, init) {
    const url = typeof input === 'string' ? input : input.url;
    if (url && url.includes('google-analytics.com/mp/collect')) {
      const u = new URL(url);
      const measurement_id = u.searchParams.get('measurement_id');
      const api_secret = <redacted>('api_secret');
      let body = init && init.body;
      try { body = JSON.parse(body); } catch {}
      console.log('[YOUBOOST_GA] outbound event captured:');
      console.log('  hardcoded measurement_id:', measurement_id);
      console.log('  hardcoded api_secret    :', api_secret);
      console.log('  body                    :', body);
    }
    return origFetch(input, init);
  };
  console.log('[YOUBOOST_GA_DECODER] installed. Trigger an event:');
  console.log('  - reload the extension to fire "install"/"update"');
  console.log('  - install another VPN/ad-blocker to fire "*_conflict"');
  console.log('  - open a YouTube video routed through the proxy to fire "video_redirect"');
})();
How to run it
  1. 1
    Open chrome://extensions, enable Developer mode.
  2. 2
    Click 'service worker' under ЮБуст.
  3. 3
    Paste the script in Console, Enter; it prints stored IDs.
  4. 4
    Trigger an event (add a blocker, reload). Each GA POST is dumped with its secret.
SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-200
SourceAI SANDBOX

Injects its own ad overlays and upgrade banners into the YouTube player

Watching YouTube, this extension can pause your video and cover it with a full-screen overlay loading a remote ad page in an iframe, plus periodic upgrade banners, blocking keyboard shortcuts while up.

Whether it runs is set remotely.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You are watching a video on YouTube.

The extension did this

On a schedule the extension pauses your video and covers the player with its own full-screen overlay that loads a remote ad/upsell page, or shows a premium-upgrade banner.

A background alarm (ShowMidRoll / ShowAdPremiumBanner) messages the active YouTube tab; the content script injects the overlay and blocks keyboard shortcuts until it closes.

02EvidenceCODE COMPARE
The code that does this

The background scheduler and the content-script overlay injector, from the shipping source.

What it actually does
Background: midroll alarm queries the active YouTube tab and tells it to show a midpoint
// Background alarm handler for the scheduled mid-roll.
if (alarm.name === Alarms.ShowMidpointMedia) {
  const { hasPremium } = await getLocal(Keys.HasPremium);
  const { featuresList } = await featureStore.getSnapshotAsync();
  const midpointEnabled = Boolean(featuresList?.[Features.MidpointMedia]);
  if (hasPremium || !midpointEnabled) return;        // skip paying users / disabled flag
  const tabs = await chrome.tabs.query({
    active: true, currentWindow: true, url: ['*://*.youtube.com/*'],
  });
  await Promise.all(tabs.map(t =>
    t.id ? chrome.tabs.sendMessage(t.id, { action: ContentAction.ShowMidpoint }) : null));
}
Content script: builds a black full-size overlay with an iframe whose src comes from remote config (midpointMediaUrls)
// Content script: inject the full-screen ad overlay over the player.
const overlay = document.createElement('div');
overlay.id = OVERLAY_ID;
overlay.style.cssText =
  'position:absolute;top:0;left:0;width:100%;height:100%;' +
  'background:black;z-index:9999;display:flex;justify-content:center;align-items:center;';
const frame = document.createElement('iframe');
frame.id = IFRAME_ID;
frame.src = midpointMediaUrls[regionKey];   // URL comes from downloaded remote config
frame.style.cssText = 'width:100%;height:100%;object-fit:contain;';
window.addEventListener('message', onFrameMessage);
overlay.appendChild(frame);
moviePlayer.appendChild(overlay);           // moviePlayer = document.getElementById('movie_player')
Content script: pauses the player and installs capture-phase keydown/keyup handlers that swallow YouTube shortcut keys
// Content script: pause playback and swallow YouTube keyboard shortcuts.
const blockKey = (e) => {
  if (['', 'ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown',
       'k','K','j','J','l','L','m','M','f','F','i','I'].includes(e.key)) {
    e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation();
  }
};
const pauseForOverlay = () => {
  postToPlayerBridge('pauseVideo');               // YT_METHOD_CALL -> injected wrapper
  document.querySelector('video')?.pause();
  document.getElementById('movie_player')?.pauseVideo?.();
  document.addEventListener('keydown', blockKey, true);   // capture phase
  document.addEventListener('keyup',   blockKey, true);
};
03EvidenceCODE COMPARE
The code that does this

The page-injected bridge letting the content script drive YouTube's player, in the MAIN world.

What it actually does
watchCoordinator.js: listens for YT_METHOD_CALL window messages and calls pauseVideo / playVideo / getPlayerState on the real player
// Runs in the page MAIN world (web-accessible resource).
window.addEventListener('message', (event) => {
  const data = event.data;
  // Only accept the extension's own tagged messages.
  if (!(data && data.source === 'YT_API_WRAPPER'
        && data.type === 'YT_METHOD_CALL'
        && ['pauseVideo','playVideo','getPlayerState'].includes(data.method))) return;
  const player = document.getElementById('movie_player');
  if (!isYoutubePlayer(player)) return;
  const result = data.method === 'getPlayerState'
    ? player.getPlayerState()      // -1..5 player state
    : (player[data.method](), true);
  window.postMessage({ source: 'YT_API_WRAPPER', type: 'YT_METHOD_RESULT',
                       method: data.method, result }, '*');
});
04EvidenceDOM DIFF
Page DOM modified

Target: the YouTube player container (#movie_player) on youtube.com/watch

A full-size black overlay div (z-index 9999) holding an ad/upsell iframe is appended over the paused player; the iframe URL comes from downloaded remote config.

Before
<div id="movie_player" class="html5-video-player playing-mode">
  <div class="html5-video-container">
    <video src="blob:https://www.youtube.com/..."></video>
  </div>
  <!-- YouTube's own controls -->
</div>
After (modified by extension)
<div id="movie_player" class="html5-video-player paused-mode">
  <div class="html5-video-container">
    <video src="blob:https://www.youtube.com/..."></video>  <!-- paused by extension -->
  </div>
  <!-- injected by the extension: -->
  <div id="midpoint_overlay" style="position:absolute;top:0;left:0;width:100%;height:100%;background:black;z-index:9999;display:flex;align-items:center;justify-content:center;">
    <iframe id="YT_API_WRAPPER_FRAME" src="https://&lt;midpointMediaUrls from remote config&gt;" style="width:100%;height:100%;object-fit:contain;"></iframe>
  </div>
</div>
05EvidenceTEMPORAL PATTERN
When this fires
On an interval

Mid-roll overlays and premium-upgrade banners are driven by chrome.alarms, not by anything you do. ShowMidRoll injects the full-screen ad overlay; ShowAdPremiumBanner toggles the banner. Both are skipped for users marked as having premium and are gated by feature flags pulled from remote config, so the cadence and whether they run at all are set by the extension's servers.

06EvidencePLAIN NOTE
Observation

What was observed: the YouTube content scripts (including the mid-roll / premium-banner code) were confirmed loaded on a YouTube watch page during dynamic analysis, and the remote feature flags that enable this behavior (video-pre-roll, sidebar-ads) were active in the extension's feature store. The exact ad/upsell pages served are not fixed in the extension — they are URLs the extension downloads from its servers (midpointMediaUrls) and can be changed remotely without an update, so the specific creative shown to any given user is not determined by the shipped code alone.

Updated 30 September 2026jddgbeighonaipjikdnfdpiefhoomlae