Is Netflix™ Extended [QVI] safe?

Medium risk

Netflix Extended transmits a persistent user ID to gathering.solutions and lets svodextensions.com request broad browser permissions.

Each time the extension logs an event, it sends a persistent UUID along with the extension version and platform details to gathering.solutions. On first install, the same UUID and extension ID are forwarded to svodextensions.com via a survey page URL. Additionally, the extension's externally_connectable channel allows svodextensions.com to prompt users to grant the extension access to all websites, beyond its declared Netflix-scoped permissions.

SVODExtensionsv8.2.35Chrome Web Store
52Risk
Who publishes it

HideApp - 69 other listings from the same operator, 15 of them carrying a finding

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

Publisher
SVODExtensions
Declared legal entity
HideApp
Registered address
1021 East Lincolnway, Cheyenne, WY 82001, US
Registered contact
HideApp LLC

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.

private.omdbapi.com
Also called by 2 other listings, including RateFlix

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

Publishers can request a review.

Findings

Persistent UUID sent to gathering.solutions on every logged event

A random identifier is generated on first run and stored permanently.

Each log event, errors included, sends it with your version and platform to gathering.solutions.

It persists indefinitely with no disclosure or consent prompt.

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

You install the extension and use it on Netflix.

Normal use, browsing titles, rating, or encountering errors, triggers log events.

The extension did this

The extension generates a permanent random ID tied to your browser and sends it with every log message to gathering.solutions.

The ID is stored in chrome.storage.sync, so it follows the browser profile even across reinstalls.

Fields sent in each POST to gathering.solutions/n/js/dlog
  • Persistent browser ID
    a3f7c821-9b2e-4d1f-80c4-1e5a7b93d204

    A random UUID generated once and stored permanently, letting gathering.solutions link every telemetry call to the same install.

  • Extension ID
    gjcgfkhgpaccjpjokgpekpgpphgaanej

    The Chrome extension's runtime ID, which also appears in the extension store URL.

  • Extension version
    8.2.34

    Which version of the extension is installed, allowing the server to correlate behavior with specific builds.

  • Platform
    chromeos

    The operating system platform string reported by the extension runtime.

  • Log message
    commandsInit success

    The text of the logged event, may include feature names, error messages, or interaction labels.

The code that does this

UUID creation and telemetry dispatch in typ.min.js

Readable version

UUID creation logic

// On first call, generate a UUID and persist it in chrome.storage.sync// On subsequent calls, return the stored valueasync function getOrCreateExtensionUserId() {  const stored = await chromeStorageGetKey('extension_user_id');  if (stored) return stored;  const uuid = self.crypto.randomUUID();  await chromeStorageSetKey('extension_user_id', uuid);  return await chromeStorageGetKey('extension_user_id');}

Telemetry dispatch

// Assembles and POSTs to https://gathering.solutions/n/js/dlog on every log callasync function logMessage(platform, namespace, message, commandId) {  const dist = getDist();            // chrome.runtime.id  const extVer = getExtensionVersion();  const extensionUserId = await getExtensionUserId();  const payload = {    dist, revision, platform, namespace,    extVer, extensionUserId, dhVer, message,    commandId: commandId ? formatCommandId(commandId) : undefined  };  await httpNodeLog(payload); // POST to gathering.solutions/n/js/dlog}
Telemetry destination
    • gathering.solutions

    Receives telemetry logs. /n/js/dlog accepts POST with extensionUserId, version, platform, message. BASE_ROUTE and nodeRootUrl both resolve here.

svodextensions.com can prompt users to grant the extension all-websites access

svodextensions.com can trigger an all-websites permission prompt via an external message channel, though the extension is normally scoped to Netflix, Wikidata, and OMDB.

Allow grants access to every site.

Not in the store listing.

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

You visit a page on svodextensions.com that sends a permission request to the extension.

Any page under https://svodextensions.com/ can initiate this; the user does not need to take a deliberate action beyond visiting the site.

The extension did this

The extension presents a Chrome permission dialog asking you to grant it access to every website you visit.

If you click Allow, the extension's access expands from Netflix, Wikidata, and OMDB to all websites indefinitely.

The code that does this

External message handler and permission escalation path

Readable version

Readable equivalent showing the two operations

// svodextensions.com can query whether <all_urls> is already granted,// then request it if not — triggering a browser permission dialog.chrome.runtime.onMessageExternal.addListener((message, sender, sendResponse) => {  if (message.op === 'should_request_all_urls_permission') {    // Returns true if permission has NOT yet been granted    chrome.permissions.contains({ origins: ['<all_urls>'] }, (has) => {      sendResponse(!has);    });    return true; // async response  }  if (message.op === 'request_all_urls_permission') {    // Shows Chrome's 'Allow extension to read/change all your data on all websites' prompt    chrome.permissions.request({ origins: ['<all_urls>'] }, (granted) => {      sendResponse({ granted });    });    return true;  }});
Relevant manifest declarations
  • Declared host permissions (default)
    *://*.netflix.com/*, *://*.wikidata.org/*, *://*.omdbapi.com/*

    The extension's normal access scope: Netflix, Wikidata, and OMDB only.

  • Optional permission
    <all_urls>

    Approving the dialog grants access to every website. Declared optional so Chrome allows the runtime request.

  • Permitted external message caller
    https://svodextensions.com/*

    Only pages under this origin can send external messages to the extension via chrome.runtime.sendMessage.

UUID and extension ID sent to svodextensions.com on install

On install, a new tab opens to a survey page at svodextensions.com carrying two unprompted tracking parameters: the persistent UUID also used for telemetry, and the extension's distribution ID, linking the install to your profile.

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

You install the extension for the first time.

The install trigger fires only once; subsequent updates do not re-open the page.

The extension did this

The extension opens a new tab to svodextensions.com with your persistent UUID and its own extension ID embedded in the URL.

The UUID is the same identifier used for telemetry logging to gathering.solutions, allowing the two services to correlate activity.

Parameters appended to the survey URL
  • Persistent browser ID (user=)
    a3f7c821-9b2e-4d1f-80c4-1e5a7b93d204

    The same random UUID used for telemetry, letting svodextensions.com identify which install just occurred.

  • Extension distribution ID (dist=)
    gjcgfkhgpaccjpjokgpekpgpphgaanej

    The Chrome extension's runtime ID, matching the Chrome Web Store identifier.

The code that does this

Install handler and URL-building code

Readable version

Readable equivalent

// On install, open the survey page with the UUID + extension ID in the URLchrome.runtime.onInstalled.addListener(async ({ reason }) => {  if (reason === chrome.runtime.OnInstalledReason.INSTALL) {    const alreadyShown = await chrome.storage.sync.get('isSurveyShowed');    if (!alreadyShown.isSurveyShowed) {      await chrome.storage.sync.set({ isSurveyShowed: true });      const user = await getOrCreateExtensionUserId(); // persistent UUID      const dist = chrome.runtime.id;                  // extension ID      const url = `https://svodextensions.com/thank-you-survey/?user=${user}&dist=${dist}`;      chrome.tabs.create({ url, active: true });    }  }});

Where it sends data

Destinations our analysis observed Netflix Extended 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.

  • private.omdbapi.com

    Netflix Extended sends data to private.omdbapi.com. One other extension we have analysed sends data here.

  • query.wikidata.org

    Netflix Extended sends data to query.wikidata.org. One other extension we have analysed sends data here.

  • gathering.solutions

    Netflix Extended sends data to gathering.solutions. No other extension we have analysed sends data here.

  • svodextensions.com

    Netflix Extended sends data to svodextensions.com. No other extension we have analysed sends data here.

Updated 30 September 2026gjcgfkhgpaccjpjokgpekpgpphgaanej