Is Cashback Ninja safe?

Medium risk

Cashback Ninja is medium risk. Cashback Ninja's background worker requests settings from cashbackninja.su using the version and a per-install UUID. It writes whatever returns into storage, including tc_auto_cashback_enabled, which drives affiliate-redirect rules.

Advantagev1.0.0.6Chrome Web Store
45Risk

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

Publishers can request a review.

Findings

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-829
SourceAI SANDBOX

Remote settings can overwrite Cashback Ninja controls

Cashback Ninja's background worker requests settings from cashbackninja.su using the version and a per-install UUID.

It writes whatever returns into storage, including tc_auto_cashback_enabled, which drives affiliate-redirect rules.

01EvidenceCAUSE EFFECT
What actually happens
You did this

The extension refreshes its cashback shop list in the background.

That refresh runs at startup when the stored refresh timestamp is missing or older than one day.

The extension did this

Before downloading the shop list, the service worker requests settings and writes the returned object into extension storage.

The write is not limited to a fixed set of expected keys.

02EvidenceNETWORK CAPTURE
Captured request
GEThttps://cashbackninja.su/1.0.0.5/AB12CD34EF56GH78IJ90KL12MN34OP56/get_settings
The shipped code parses the response as JSON and applies object responses to chrome.storage.local.
03EvidenceFIELD TABLE
Fields used by the remote settings channel
FieldValueWhy it matters
Extension version
1.0.0.5Lets the settings endpoint return a response tailored to the exact extension build you installed.
Per-install ID
AB12CD34EF56GH78IJ90KL12MN34OP56Lets the settings endpoint distinguish this browser installation from other installations.
Returned settings object
{"tc_auto_cashback_enabled":true}Any key in the returned object is written into local extension storage for later code paths to read.
Affiliate redirect toggle
tc_auto_cashback_enabled: trueControls whether the extension installs browser redirect rules for cashback merchant links.
04EvidenceCODE COMPARE
The code that does this

The shipped background code applies remote settings before installing redirect rules

What it actually does
Persistent per-install UUIDscripts/bg.js
async function getUuid() {
    while (UID_LOCK) {
        await timeout(10);
    }
    UID_LOCK = true;
    let {uuid} = await chrome.storage.local.get({uuid: false});
    if (!uuid) {
        uuid = generateParam();
        await chrome.storage.local.set({uuid: uuid});
    }
    UID_LOCK = false;
    return uuid;
}
Remote settings fetch and storage writescripts/bg.js
async function updateList() {
    await removeOldRules();
    const uuid = await getUuid();
    const version = chrome.runtime.getManifest().version;

    /*
        sync user settings
    */
    try {
        const settings = await (await fetch(`https://cashbackninja.su/${version}/${uuid}/get_settings`)).json();

        if (settings && typeof settings == 'object') {
            await chrome.storage.local.set(settings);
        }
    }
    catch (e) {}

    const tc_list = await (await fetch(`https://cashbackninja.su/${cmp_id}/${uuid}/${version}/shops.json`)).json();
    const {tc_last_usage, tc_auto_cashback_enabled} = await chrome.storage.local.get({tc_last_usage: {}, tc_auto_cashback_enabled: false});
    let declarativeRules = [];
    let curId = 1;
    if (tc_list.hasOwnProperty('links')) {
        for (let key_domain in tc_list.links) {
            const mainRule = tc_list.links[key_domain];
            if (mainRule.image) {
                try {
                    const b64_img = await imageToBase64(mainRule.image);
                    if (b64_img) {
                        mainRule.image = b64_img;
                    }
                }
                catch(e) {
                }
            }
            const rules = mainRule.rules;
            for (let rule of rules) {
                if (!rule.hasOwnProperty('url')) {
                    rule.url = `https://${key_domain}/`;
                }
                const {subdomain, domain, pathname} = _parseUrl(rule.url);


                let priority = 1;
                let filterType = 'requestDomains';
                let filter = [domain];
                if (rule.url.indexOf('*') !== -1) {
                    const urlObject = new URL(rule.url.replace(/\*/g, ''));
                    let path = urlObject.pathname;
                    if (path.indexOf('/') !== 0) {
                        path = '/' + path;
                    }
                    let urlFilter = `||${domain}${path.replace(/\/$/, '')}`;
                    filterType = 'urlFilter';
                    filter = urlFilter;
                }
                const durl = new URL(rule.durl);
                const durl_base = durl.hostname.replace(/^www\./, '');
                if (rule.durl) {
                    rule.dcRule = {
                        id: curId,
                        priority: priority,
                        action: {type: 'redirect', redirect: {'url': rule.durl}},
                        condition: {
                            excludedInitiatorDomains: [domain, durl_base],
                            [filterType]: filter,
                            resourceTypes: ['main_frame']
                        }
                    }
                }
                curId++;
            }
            const curTime = (new Date()).getTime();
            const lastUsage = tc_last_usage[key_domain] || 0;
            let delay = mainRule.hasOwnProperty('delay') ? mainRule.delay : RULE_DELAY;
            if ((curTime - lastUsage) > delay) {
                mainRule.should_add = true;
                declarativeRules.push(...mainRule.rules.map(item => item.dcRule));
            }
            else {
                mainRule.isActivated = true;
                mainRule.isShown = true;
            }
        }
    }
    if (declarativeRules.length && tc_auto_cashback_enabled) {
        await chrome.declarativeNetRequest.updateSessionRules({
            addRules: declarativeRules
        });
    }
    await chrome.storage.local.set({tc_list});
    await chrome.alarms.create('update_rules', {
        periodInMinutes: 0.5
    });
}
05EvidenceTHIRD PARTY LIST
Remote hosts involved in the settings path
  • cashbackninja.su

    Receives the version-and-UUID settings request and returns the JSON object that updateList() writes into extension storage.

  • tp.cashbackninja.su

    Receives the per-install UUID in an install-time welcome URL opened by the extension.

Updated 10 September 2026dbjlkjnlhjgnabhmibofkhfgcnkgloig