Is Spending Calculator for Swiggy™ and Zomato™ safe?
Spending Calculator for Swiggy and Zomato is medium risk. Spending Calculator creates a persistent random ID, stored as siteClientId, sent as uid to backend.spendingcalculator.xyz registering site-access config. A captured request sent this UUID to /api/s/d; code also posts it to /api/s/r first.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Startup UUID sent to Spending Calculator backend
Spending Calculator creates a persistent random ID, stored as siteClientId, sent as uid to backend.spendingcalculator.xyz registering site-access config.
A captured request sent this UUID to /api/s/d; code also posts it to /api/s/r first.
You install the extension or start the browser.
The same registration function also runs when the background worker loads.
The extension creates or reuses a persistent browser identifier and sends it to its backend.
The identifier is stored locally as siteClientId and sent in the uid field.
| Field | Value | Why it matters | |
|---|---|---|---|
Browser identifier | 374fc245-60c7-4ad9-906c-29cf2d58299a | This gives the backend a stable value that can recognize this browser across extension restarts. | |
Stored identifier key | siteClientId | This keeps the identifier available for later background runs instead of creating a new value each time. | |
Request field | uid | This is the payload field that carries the browser identifier to the backend. |
{
"uid": "374fc245-60c7-4ad9-906c-29cf2d58299a"
}Background code that creates, stores, and posts the identifier
const BACKEND_BASE_URL = "https://backend.spendingcalculator.xyz";
const SITE_CLIENT_KEY = "siteClientId";
const SITE_DOMAINS_KEY = "siteDomains";
let siteRefreshPromise = null;
const postToBackend = async (path, payload) => {
const response = await fetch(`${BACKEND_BASE_URL}${path}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
});
if (!response.ok) {
throw new Error(`Backend request failed with status ${response.status}`);
}
return response.json();
};const createClientId = () => {
if (typeof crypto.randomUUID === "function") {
return crypto.randomUUID();
}
return `${Date.now().toString(36)}-${crypto.getRandomValues(new Uint32Array(4)).join("-")}`;
};
const prepareSiteAccess = async () => {
const stored = await chrome.storage.local.get([
SITE_CLIENT_KEY,
SITE_DOMAINS_KEY,
]);
const clientId = stored[SITE_CLIENT_KEY] || createClientId();
if (!stored[SITE_CLIENT_KEY]) {
await chrome.storage.local.set({ [SITE_CLIENT_KEY]: clientId });
}
await postToBackend("/api/s/r", { uid: clientId });
const release = await postToBackend("/api/s/d", { uid: clientId });
const domains = Array.isArray(release?.adslist) ? release.adslist : [];
await chrome.storage.local.set({
[SITE_DOMAINS_KEY]: domains,
});
};const refreshSiteAccess = () => {
if (!siteRefreshPromise) {
siteRefreshPromise = prepareSiteAccess()
.catch(() => {})
.finally(() => {
siteRefreshPromise = null;
});
}
return siteRefreshPromise;
};
chrome.runtime.onInstalled.addListener((details) => {
if (details.reason == "install") {
chrome.tabs.create({ url: "https://bit.ly/fooddyin" });
chrome.notifications.create(
{
type: "basic",
iconUrl: chrome.runtime.getURL("Icons/Icon 32.png"),
title: "Hey, 😃 Foodie!",
message: "Thanks for installing Spending Calculator!",
silent: false,
},
() => { }
);
} else if (details.reason == "update") {
var thisVersion = chrome.runtime.getManifest().version;
}
if (chrome.runtime.setUninstallURL) {
chrome.runtime.setUninstallURL("https://bit.ly/fooddyuin");
}
refreshSiteAccess();
});
chrome.runtime.onStartup.addListener(() => {
refreshSiteAccess();
});
refreshSiteAccess();- backend.spendingcalculator.xyz
Receives the uid value during site-access registration and returns the ad/domain configuration used by the extension.
What it can do
Permissions this extension asks for, as declared in version 1.7. 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 1.8, which we have not unpacked yet.
Read and change your data on every site you visit
<all_urls>
See the address and title of every tab you have open
tabs
Store data in your browser
storage
Act on the current tab, but only after you click the extension
activeTab
Show you desktop notifications
notifications