Is Blackfy safe?
Blackfy fetches a Google Sheets affiliate map and redirects matching visited domains to configured affiliate URLs.
Blackfy downloads a remote Google Sheets CSV that maps domains to affiliate links, then watches completed tab navigations across sites. When a visited hostname matches the downloaded map, it updates the tab to the configured affiliate URL.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Remote Spreadsheet Config Drives Whole-Page Affiliate Redirects
Blackfy fetches a Google Sheet at startup and on consent changes, then replaces the full tab URL, query included, with the sheet's affiliate link on domain matches.
Confirmed on booking.com: redirected in ~1s to a link with referral params.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-829
- Source
- Dynamic sandbox
You navigate to a site listed in Blackfy's remote configuration, such as booking.com.
Blackfy replaces the tab's URL with the affiliate link mapped to that domain in a live Google Sheet, in place of the page you navigated to.
Fires on every completed navigation once the install-time consent flag is set, which defaults to true on install.
200 OK, CSV body of domain,affiliate_url pairs, including booking.com,https://cutt.ly/crRorz3y and aliexpress.com,https://s.click.aliexpress.com/e/_c3f298bx. Fetched with cache disabled, so each fetch reflects the sheet's current contents.
Fired roughly one second after booking.com finished loading, matching the affiliate link the sheet listed for that domain. The tab lands back on booking.com carrying new referral query parameters (chal_t, force_referer) in place of whatever the original URL carried.
same navigation
You didYou land on hostinger.com through a link that carries its own referral code (?subid=...).
The extension didBlackfy's redirect lands you on hostinger.com with its own code instead (?REFERRALCODE=1GIDAN04); the original subid value is absent from the URL that follows.
same navigation
You didYou land on agoda.com through a link that carries its own partner id (?aid=...).
The extension didThe redirect chain lands you on agoda.com with Blackfy's partner id in its place (?cid=1842467), and the merchant's own backend (agoda.com/api/gw/Cms/Lookup) subsequently reflects that id.
same navigation
You didYou land on expedia.com, or on a page Opera referred you to.
The extension didThe navigation is routed through r.salegains.com using Blackfy's own ids (cid=21 / mid=51435, mid=13304) before reaching the merchant, ahead of any tag the original link carried.
The consent check, remote-config fetch, and redirect listener, from the extension's shipping source.
Consent check and remote CSV fetch (annotated)
// Resolves true only when the stored consent flag is set.function hasUserConsented() { return new Promise(resolve => { chrome.storage.local.get(["userConsent"], (result) => { resolve(result.userConsent === true); }); });}// Downloads the current domain -> affiliate-URL map from the Google Sheet// and replaces the in-memory table the redirect listener reads from.async function fetchAffiliateLinks() { try { const response = await fetch(SHEET_URL, { cache: "no-store" }); if (!response.ok) throw new Error("Sheet fetch failed"); const text = await response.text(); // Simple CSV: domain, url const rows = text.split("\n").map(row => row.split(",")); const updatedLinks = {}; rows.forEach((row, index) => { if (index === 0) return; // header row let rawDomain = row[0]?.trim().toLowerCase().replace(/"/g, ""); if (!rawDomain) return; let cleanDomain = rawDomain.replace(/^www\./, "").replace(/\s+/g, ""); let affiliateUrl = row[1]?.trim().replace(/"/g, ""); if (!affiliateUrl) return; if (!/^https?:\/\//i.test(affiliateUrl)) { affiliateUrl = "https://" + affiliateUrl; } updatedLinks[cleanDomain] = affiliateUrl; // e.g. "booking.com" -> "https://cutt.ly/crRorz3y" }); affiliateLinks = updatedLinks; } catch (e) { // no error is surfaced if the fetch or parse fails }}The redirect listener (annotated)
// Fires on every navigation that finishes loading in any tab.chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => { if (changeInfo.status !== "complete" || !tab?.url) return; const userConsented = await hasUserConsented(); if (!userConsented) return; let urlObj; try { urlObj = new URL(tab.url); } catch { return; } // Looks up the finished tab's own hostname in the remotely-fetched map. const domain = urlObj.hostname.toLowerCase().replace(/^www\./, "").replace(/\s+/g, ""); const target = affiliateLinks[domain]; if (target) { // Only redirects once per domain per browser session. if (redirectedDomains.has(domain)) return; redirectedDomains.add(domain); chrome.storage.session.set({ redirected: Array.from(redirectedDomains) }); // Replaces the whole tab URL, not just a query parameter. chrome.tabs.update(tabId, { url: target }, () => {}); }});- docs.google.com
Serves the CSV that supplies the live domain list and affiliate destinations; fetched with caching disabled on every startup and consent change.
- cutt.ly
Redirect target confirmed for booking.com during dynamic analysis.
- s.click.aliexpress.com
Redirect target listed in the fetched sheet for aliexpress.com.
- r.salegains.com
Redirect network observed carrying Blackfy's own ids for other mapped merchants (e.g. expedia.com).
What it can do
Permissions this extension asks for, as declared in version 1.1.1. 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
<all_urls>
Read and change your data on docs.google.com
https://docs.google.com/*
Store data in your browser
storage
See the address and title of every tab you have open
tabs
Where it sends data
Destinations our analysis observed Blackfy 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.
- docs.google.com
Blackfy sends data to docs.google.com. 20 other extensions we have analysed send data here.