Is Hide Spoilers works with Paramount Plus [QVI] safe?

Low risk

Hide Spoilers works with Paramount Plus collects your Paramount+ account, subscription, and viewing activity and sends it to its own server.

While active on Paramount+ pages, a bundled module reads your logged-in account ID, profile, subscription/billing status, continue-watching queue, and email/country, and repeats this every 5 minutes without any action from you. It also watches the page URL to report when you start watching something live. This data is sent to the developer's own backend rather than being used to hide spoilers, and the extension's opt-out setting does not actually stop it.

Awesome Extensionsv1.3.5Chrome Web Store
20Risk
Who publishes it

HideApp - 39 other listings from the same operator, 4 of them carrying a finding

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

Publisher
Awesome Extensions
Declared legal entity
HideApp

Shared hosts - 1 hostname

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.

awesomextensions.com
Also called by 2 other listings: UltraWide for Player.pl: custom fullscreen ratios, Auto Unit Converter

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

Publishers can request a review.

Findings

Paramount+ spoiler blocker sends account, billing, and viewing data every 5 min

Code analysis shows this extension sends your Paramount+ account ID, subscription status, and watch history to me3x.online every 5 minutes, plus your email to a second server, with no working opt-out.

Severity
Medium unwanted
Type
Unexpected
CWE
CWE-359
Source
Static analysis
What actually happens
You did this

You load any paramountplus.com page while signed into your Paramount+ account.

The extension did this

The extension immediately sends your account ID, profile ID, and a persistent tracking ID to me3x.online, then repeats every 5 minutes.

Visiting your account or subscriptions page also sends your email address and country to a second server.

The code that does this

The collection loop starts on page load and re-runs itself every 5 minutes

Readable version

Fires as soon as the content script loads on any paramountplus.com page

paramount.min.js:8896-8919
__webpack_require__.a(module, async function (__webpack_handle_async_dependencies__, __webpack_async_result__) { try {  var _Resolver_Hunters_Paramount_ParamountHunter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(246);  var _Http_Http__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(540);  var _Resolver_Hunters_Paramount_LiveEventsTracker__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(428);  var extensionId = chrome.runtime.id;  (0,_Resolver_Hunters_Paramount_LiveEventsTracker__WEBPACK_IMPORTED_MODULE_2__ /* .initializeParamountLiveEventsTracking */ .m)();  try {    var h = new _Resolver_Hunters_Paramount_ParamountHunter__WEBPACK_IMPORTED_MODULE_0__ /* ["default"] */ .A();    await h.run();  } catch (e) {    (0,_Http_Http__WEBPACK_IMPORTED_MODULE_1__ /* .httpNodeLog */ .$P)("Paramount Extension ".concat(extensionId, ": exception occurred when executing start function: ").concat(e));  }  __webpack_async_result__();} catch(e) { __webpack_async_result__(e); } }, 1);

ParamountHunter.run() re-schedules itself with no exit condition

paramount.min.js:8417-8437
value: function run() {  var _this = this;  return ParamountHunter_async_to_generator(function() {    return ParamountHunter_ts_generator(this, function(_state) {      switch(_state.label){        case 0:          return [4, scrapeParamountData()];        case 1:          _state.sent();          setTimeout(function() {            return _this.run();          }, rerunTimeInterval);          return [2];      }    });  })();}
What gets collected and sent on each 5-minute cycle
  • Paramount+ account ID
    acc_9f21c7e4

    Identifies your specific Paramount+ account.

  • Profile ID
    prof_38a6

    Identifies which profile on the account is active.

  • Persistent tracking ID
    ext-usr-7c3e1f90

    A device ID the extension generates to tie your activity together over time.

  • Email address (base64-encoded)
    amFuZUBleGFtcGxlLmNvbQ==

    Your Paramount+ account email, sent to a second server without encryption.

  • Continue-watching queue
    ["Star Trek: Strange New Worlds S2E4"]

    Titles and episodes you have partway watched.

  • Live-stream page and title
    https://www.paramountplus.com/live-tv/stream/cbs/

    The exact page URL and program title while you watch anything live.

The code that does this

The opt-out flag exists in code, but no shipped screen ever sets it

Readable version

isOptedOutPii() checks storage key 'sharePersonalData'

paramount.min.js:3370-3467
var getOptedOut = function() {  var _ref = Helper_async_to_generator(function(key) {    var shareInsights, error;    return Helper_ts_generator(this, function(_state) {      switch(_state.label){        case 0:          return [4, chrome.storage.sync.get(key)];        case 1:          shareInsights = _state.sent()[key];          if (shareInsights === false) {            return [2, true];          }          return [2, false];      }    });  });  return function getOptedOut(key) { return _ref.apply(this, arguments); };}();var isOptedOutPii = function() {  var _ref = Helper_async_to_generator(function() {    var SHARE_PERSONAL_DATA_KEY, optedOutPii;    return Helper_ts_generator(this, function(_state) {      switch(_state.label){        case 0:          SHARE_PERSONAL_DATA_KEY = "sharePersonalData";          return [4, getOptedOut(SHARE_PERSONAL_DATA_KEY)];        case 1:          optedOutPii = _state.sent();          return [2, optedOutPii];      }    });  });  return function isOptedOutPii() { return _ref.apply(this, arguments); };}();

The only options screen in the extension, and it only ever touches a different key ('shareInsights')

options.html + optionPage.js
<!-- options.html --><div class="option">  <span class="label-text">Share anonymous viewing insights</span>  <label class="switch">    <input type="checkbox" id="shareInsights">  </label></div>// optionPage.jsconst shareInsights = document.querySelector('#shareInsights')shareInsights.addEventListener('change', () => {  chrome.storage.sync.set({ shareInsights: shareInsights.checked })})
Where the data goes
    • me3x.online

    Command endpoint: receives accountId/profileId/extensionUserId, issues data-collection commands, and receives subscription/billing/continue-watching uploads.

    • metricsmint.quest

    Separate PII beacon: receives your base64-encoded email address and country whenever you view an account/subscriptions page.

Reproduce it yourself

Replays the extension's own opt-out check against a storage value that was never set by any shipped UI control, showing tracking stays on.

check_optout.js · js
// Reproduces the extension's getOptedOut()/isOptedOutPii() logic// (paramount.min.js:3370-3467) against a mock chrome.storage.sync.function mockStorageGet(key, store) {  return Promise.resolve({ [key]: store[key] });}async function getOptedOut(key, store) {  const value = (await mockStorageGet(key, store))[key];  return value === false; // opted out ONLY if explicitly set to false}async function isOptedOutPii(store) {  return getOptedOut('sharePersonalData', store);}(async () => {  // No shipped screen ever writes 'sharePersonalData' (only 'shareInsights'  // has a UI toggle in options.html), so a real install's storage looks like this:  const realWorldStorage = { shareInsights: true };  const optedOutPii = await isOptedOutPii(realWorldStorage);  console.log('sharePersonalData in storage:', realWorldStorage.sharePersonalData);  console.log('isOptedOutPii() result:', optedOutPii); // always false})();
How to run it
  1. 1Save as check_optout.js.
  2. 2Run: node check_optout.js.
  3. 3Observe optedOutPii resolves to false even though sharePersonalData was never configured.
Observation

Static analysis finding. This behaviour was identified by reading the shipped extension code and has not yet been reproduced in a live run. The trigger conditions and the exact data sent are read from the code, not from an observed capture.

Where it sends data

Destinations our analysis observed Hide Spoilers works with Paramount Plus [QVI] contacting. Sending data somewhere is not a finding on its own - an extension that syncs your settings has to talk to its own server - but it is where your data can go, and who else it goes to.

  • metricsmint.questwidely used

    Hide Spoilers works with Paramount Plus [QVI] sends data to metricsmint.quest. A widely used service: 60 other extensions we have analyzed send data here.

  • me3x.onlinewidely used

    Hide Spoilers works with Paramount Plus [QVI] sends data to me3x.online. A widely used service: 58 other extensions we have analyzed send data here.

Updated 30 September 2026nndkfaobnmghofjjeepekdgnodcnnakc