Is Story Saver safe?

High risk

Story Saver is high risk. Each startup, Story Saver sends ex.zework.com a per-install ID. First run creates a 25-char random string plus language, sent via '?id='; later starts resend it via '?on='. Captured: GET ex.zework.com/?on=TWzOFYmRCW8Iv2dI4m46PDQDMen-GB.…

75Risk
Who publishes it

ad - 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
ad

Same store account

1 other listing published from this account. 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

SeverityHIGH
ClassUNWANTED
TypeUnexpected
CWECWE-359
SourceAI SANDBOX

Persistent tracking beacon sent to ex.zework.com on every startup

Each startup, Story Saver sends ex.zework.com a per-install ID.

First run creates a 25-char random string plus language, sent via '?id='; later starts resend it via '?on='.

Captured: GET ex.zework.com/?on=TWzOFYmRCW8Iv2dI4m46PDQDMen-GB.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You start your browser with Story Saver installed.

The extension did this

The extension sends a GET request to ex.zework.com with a persistent identifier tied to your installation.

No user interaction, no download, no story viewed. The request fires on every startup automatically.

02EvidenceNETWORK CAPTURE
Captured request
GEThttps://ex.zework.com/?on=TWzOFYmRCW8Iv2dI4m46PDQDMen-GB
Returning-user beacon. Observed during dynamic analysis. The ?on= parameter carries the stored KEYUSER value.
03EvidenceFIELD TABLE
What ex.zework.com receives on each startup:
FieldValueWhy it matters
Your installation ID
TWzOFYmRCW8Iv2dI4m46PDQDMA 25-character random string generated on first run and stored permanently, letting the server recognize your install across sessions.
Browser language
en-GBYour configured browser locale, appended to the ID during first-run generation. Reveals a language/region signal.
04EvidenceSTORAGE DUMP
What's stored on your device

The stored tracking value: 25 random characters plus the browser language code at first install. Written once, sent on every later startup.

Locationchrome.storage.local key 'KEYUSER'
Contents
TWzOFYmRCW8Iv2dI4m46PDQDMen-GB
05EvidenceCODE COMPARE
The code that does this

The beacon code in background.js:

What it actually does
// Runs at top-level service worker scope — fires on every SW startup.
chrome.storage.local.get('KEYUSER', function(result) {
    var iduser = result.KEYUSER;
    if (iduser) {
        // Returning install: report existing ID
        fetch("https://ex.zework.com/?on=" + iduser);
    } else {
        // First run: generate a 25-char random ID + browser language, store, then report
        var keyidmake = randomkey(25) + navigator.language;
        chrome.storage.local.set({ "KEYUSER": keyidmake });
        fetch("https://ex.zework.com/?id=" + keyidmake);
    }
});
06EvidenceTHIRD PARTY LIST
Where the tracking ID is transmitted:
  • ex.zework.com

    Receives the per-install tracking ID on every service-worker startup. Domain is listed in host_permissions (*.zework.com). Ownership isn't publicly disclosed in the CWS listing.

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-359
SourceAI SANDBOX

Browser fingerprint with language code transmitted to ex.zework.com

Story Saver builds a tracking ID at install from a random string plus browser language, sent to ex.zework.com via ?id=.

Later startups resend it via ?on=.

Captured: ?id=hxAQRRPlggQxWu2pJiWDpsqK9en-GB, ?on=TWzOFYmRCW8Iv2dI4m46PDQDMen-GB.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You install Story Saver for the first time.

The extension did this

The extension generates a persistent identifier that includes your browser's language setting and transmits it to ex.zework.com.

The identifier is stored in chrome.storage.local and re-sent on every subsequent startup, allowing the server to track your install across sessions.

02EvidenceFIELD TABLE
The identifier transmitted to ex.zework.com:
FieldValueWhy it matters
Random component
hxAQRRPlggQxWu2pJiWDpsqK9A 25-character string generated once at install using Math.random(). Provides uniqueness across users.
Browser language
en-GBYour navigator.language value appended to the random string. Encodes language and regional locale in the tracking key.
03EvidenceNETWORK CAPTURE
Captured request
GEThttps://ex.zework.com/?id=hxAQRRPlggQxWu2pJiWDpsqK9en-GB
First-run registration beacon. Observed during dynamic analysis. The ?id= parameter carries the newly generated composite identifier including the 'en-GB' language suffix.
04EvidenceCODE COMPARE
The code that does this

Identifier generation and transmission (background.js:11995-12015):

What it actually does
// Runs at top-level service worker scope on every startup.
chrome.storage.local.get('KEYUSER', function(result) {
    var iduser = result.KEYUSER;
    if (iduser) {
        // Returning user: resend stored identifier
        fetch("https://ex.zework.com/?on=" + iduser);
    } else {
        // First run: generate composite ID and register with server
        var keyidmake = randomkey(25) + navigator.language; // e.g. "hxAQRRPlggQxWu2pJiWDpsqK9en-GB"
        chrome.storage.local.set({ "KEYUSER": keyidmake });
        fetch("https://ex.zework.com/?id=" + keyidmake);
    }
});

// randomkey() helper (background.js:19-28):
function randomkey(length) {
    let result = '';
    const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    while (result.length < length) {
        result += characters.charAt(Math.floor(Math.random() * characters.length));
    }
    return result;
}
05EvidenceTHIRD PARTY LIST
Where the identifier is sent:
  • ex.zework.com

    Receives the composite ID on first run (?id=) and every startup after (?on=). Declared in manifest as *.zework.com. Ownership not disclosed in the CWS listing.

What it can do

Permissions this extension asks for, as declared in version 2.9.30. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to. The current listed version is 3.0.8, which we have not unpacked yet.

  • Read and change your data on instagram.com

    *://*.instagram.com/*

  • Read and change your data on facebook.com

    *://*.facebook.com/*

  • Read and change your data on whatsapp.com

    *://*.whatsapp.com/*

  • Read and change your data on fbcdn.net

    *://*.fbcdn.net/*

  • Read and change your data on zework.com

    *://*.zework.com/*

  • React to what is on a page without reading the page

    declarativeContent

  • Start, monitor and manage your downloads

    downloads

  • Run its own code inside the pages you visit

    scripting

  • Store data in your browser

    storage

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

    tabs

Updated 30 September 2026mafcolokinicfdmlidhaebadidhdehpk