Is Cashback Ninja safe?
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.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
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.
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.
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.
| Field | Value | Why it matters | |
|---|---|---|---|
Extension version | 1.0.0.5 | Lets the settings endpoint return a response tailored to the exact extension build you installed. | |
Per-install ID | AB12CD34EF56GH78IJ90KL12MN34OP56 | Lets 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: true | Controls whether the extension installs browser redirect rules for cashback merchant links. |
The shipped background code applies remote settings before installing redirect rules
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;
}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
});
}- 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.