Is BeFrugal: Automatic Coupons, Highest CashBack safe?
BeFrugal sends your installed extension list to its servers and can disable server-selected extensions.
It uses the browser management permission to read each installed extension's ID, name, description, and version, then posts that list to tbwsjs.befrugal.com. The same flow fetches a server-provided list of extension IDs and disables matching enabled extensions; its checkout detection also sends retailer checkout and order-confirmation URLs with the BeFrugal user token.
Who publishes itBeFrugal - no other listings under this identity, 4 shared hostnames
BeFrugal - no other listings under this identity, 4 shared hostnames
What this publisher told the store about itself, and the other listings that told it the same thing.
Shared hosts - 4 hostnames
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.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Extension inventory is reported before add-ons are disabled
The source shows the disable flow asks for management access, reads your installed extensions, and sends each one's ID, name, description, and version to BeFrugal, then asks which IDs to disable and turns off any enabled match.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-506
- Source
- Dynamic sandbox
You start the disable-conflicting-extensions flow from the extension's prompt.
The click handler sends the getAllExtensions action to the background script.
The extension reports your installed add-ons to BeFrugal and turns off enabled add-ons selected by BeFrugal's response.
The flow requests management access, reads installed extensions, posts their metadata, fetches a disable list, and disables matching extensions.
- Installed add-on IDaapbdbdomjkkjkaonfhkkikfgjllcleb (illustrative)
Uniquely identifies each installed extension. Can reveal security tools, shopping extensions, developer tools, or other add-ons you use.
- Installed add-on nameGoogle Translate (illustrative)
This gives a readable name for each add-on in your browser. It makes the extension inventory understandable without looking up IDs.
- Installed add-on descriptionView translations easily as you browse the web. (illustrative)
This adds context about what each add-on does. It can expose what kinds of browser tools you rely on.
- Installed add-on version2.0.16 (illustrative)
This shows which release of each installed add-on you have. It can help distinguish patched and unpatched versions.
- BeFrugal user tokenbf_k9m4q2_t7xv3a (illustrative)
Links the inventory request to the extension's BeFrugal account or guest identity, tying it to your browser profile.
The verification evidence confirms the source constructs this POST in the disable flow; no captured request body was recorded.
- Content-Type
- application/x-www-form-urlencoded
Reads installed extensions, posts their metadata, then disables server-selected matches.
Readable equivalent of the prompt button
disable/disable_page1.jsdisableButton.addEventListener("click", function () { _sendDisablingMessage("getAllExtensions", null, function (results) { if (Array.isArray(results) && results.length > 0) { const encodedResults = encodeURIComponent(JSON.stringify(results)); _sendDisablingMessage("OpenDialog", { newURL: "disable/disable_page2.html?q=" + encodedResults + "&localparent=" + disableParams["localparent"], newWidth: 400, newHeight: 552, results: results, isUnknown: false }); return; } _sendDisablingMessage("OpenDialog", { newWidth: 400, newHeight: 235, newURL: "disable/disable_page3.html?localparent=" + disableParams["localparent"], isUnknown: false }); });});Readable equivalent of the background disable logic
js/shoptoolbar.jsfunction _getDisableExtensionsList(callback) { const disabledIds = []; Promise.all([BfrlTool.BrowserStorage.UserToken, shoptoolbar.ToolbarVersionPromise]) .then(function (values) { const userToken = values[0]; const toolbarVersion = values[1]; const url = shoptoolbar.Format("{0}/wssimple.asmx/GetDisableAbleExtensions", shoptoolbar.APISite); shoptoolbar.FetchJsonPost(url, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: shoptoolbar.Format("UserToken={0}&toolbarversion={1}", userToken, toolbarVersion) }).then(function (response) { if (response) { for (let i = 0; i < response.length; i++) { if (!disabledIds.includes(response[i].ExtensionId)) { disabledIds.push(response[i].ExtensionId); } } } callback(disabledIds); }); });}DisableSystem._GetAllExtensions = function (callback) { browserAdapter.GetActiveTab(true, function (tab) { browserAdapter._SendTabMessage(tab.id, { action: "focusPermissionPopup", targetScript: "autoApplyContent.js" }); const isMac = typeof navigator !== "undefined" && /mac|osx|os x/i.test(navigator.userAgent); browserAdapter._SendTabMessage(tab.id, { targetScript: "contentscript.js", action: "addOverlay", isMac: isMac }); }); _requestPermission(function (granted) { browserAdapter.GetActiveTab(true, function (tab) { browserAdapter._SendTabMessage(tab.id, { targetScript: "contentscript.js", action: "removeOverlay" }); }); if (!granted) { return; } browserAdapter.GetActiveTab(true, function (tab) { browserAdapter._SendTabMessage(tab.id, { targetScript: "contentscript.js", action: "removeQuickTip" }); }); _getDisableExtensionsList(function (serverIds) { _getInstalledExtensions(function (installedExtensions) { Promise.all([BfrlTool.BrowserStorage.UserToken, shoptoolbar.ToolbarVersionPromise]) .then(function (values) { const userToken = values[0]; const toolbarVersion = values[1]; const url = shoptoolbar.APISite + "/wssimple.asmx/UserExtensionsUpsert"; const body = shoptoolbar.Format( "extensions={0}&UserToken={1}&toolbarversion={2}", JSON.stringify(installedExtensions.map(function (extension) { return { id: extension.id, name: encodeURIComponent(extension.name.replace(/[^a-zA-Z0-9]/g, "")), description: encodeURIComponent(extension.description.replace(/[^a-zA-Z0-9]/g, "")), version: encodeURIComponent(extension.version) }; })), userToken, toolbarVersion ); shoptoolbar.Post(url, body); }); const toDisable = []; for (const index in installedExtensions) { const extension = installedExtensions[index]; if (serverIds.includes(extension.id) && extension.enabled) { toDisable.push(extension); } } if (toDisable.length > 0) { const disableOne = function (extension, done) { chrome.management.setEnabled(extension.id, false, function () { done(); }); }; toDisable.reduce(function (promise, extension) { return promise.then(function () { return new Promise(function (resolve) { disableOne(extension, resolve); }); }); }, Promise.resolve()).then(function () { callback(toDisable); }); } else { callback([]); } }); }); });};- tbwsjs.befrugal.com
Receives the installed-extension inventory through /wssimple.asmx/UserExtensionsUpsert and returns server-selected extension IDs through /wssimple.asmx/GetDisableAbleExtensions.
What it can do
Permissions this extension asks for, as declared in version 2025.6.247.0. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.
Read and change your data on every site you visit
*://*/*
See the address and title of every tab you have open
tabs
Watch every request your browser makes
webRequest
Watch, block and rewrite every request your browser makes
webRequestBlocking
Store an unlimited amount of data in your browser
unlimitedStorage
Store data in your browser
storage
See, disable and uninstall your other extensions, including your security ones
management
Where it sends data
Destinations our analysis observed BeFrugal: Automatic Coupons, Highest CashBack 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.
- tbwsjs.befrugal.com
BeFrugal: Automatic Coupons, Highest CashBack sends data to tbwsjs.befrugal.com. One other extension we have analysed sends data here.