Is Somiibo safe?

Medium risk

Somiibo redirects shopping and rewards sites through hardcoded affiliate/referral links.

Somiibo runs a content script on all HTTP and HTTPS pages and checks the current page hostname against a hardcoded list of shopping and rewards sites. When a site matches, it rewrites the page URL to a referral destination such as Giftly, Honeygain, Pawns, NordVPN, or Rakuten, then stores a timestamp to avoid repeating the redirect for 24 hours.

ITW Creative Worksv1.0.7Chrome Web Store
48Risk
Who publishes it

ITW Creative Works - no other listings under this identity, 2 shared hostnames

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

Publisher
ITW Creative Works
Declared legal entity
ITW Creative Works
Registered address
4001 Inglewood Ave 101-385, Redondo Beach, CA 90278, US
Registered contact
Ian Wiedenman

Shared hosts - 2 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.

lolli.com
Also called by 5 other listings, including Lolli
ref.nordvpn.com
Also called by 7 other listings, including NordVPN, NordVPN - a VPN proxy extension for Firefox

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

Publishers can request a review.

Findings

Affiliate Link Redirects on Shopping and Rewards Sites

Dynamic analysis: the content script rewrites the tab URL for 13 hardcoded shopping/cashback sites, replacing any existing referral code, even accepted ones, with its own.

Opt-out is an undocumented URL parameter, absent from the listing.

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

You navigate directly to pawns.app (or one of 12 other hardcoded shopping, cashback, or referral sites).

The extension did this

Before the page finishes loading, the extension rewrites the tab's address to its own referral link for that site.

No click or user action on the page is required; the rewrite happens on ordinary navigation.

The code that does this

The hardcoded referral table and redirect logic, from the extension's shipping source.

Readable version

Module 836 (affiliatizer) -- cleaned up equivalent

const AFFILIATE_TABLE = [  { id: 'amazon', match: /amazon.com/, replace: { href: 'https://giftly.app/product?...tag=itwcw1--promo-server-20...' } },  { id: 'factor', match: /factor75.com/, replace: { href: 'https://www.factor75.com/plans?...discount_comm_id=cd2585e3-...' } },  { id: 'honeygain', match: /honeygain.com/, replace: { href: 'https://r.honeygain.me/IANA1DCDB1' } },  { id: 'jumptask', match: /app.jumptask.io/, replace: { href: 'https://www.jumptask.io/r/dazelafojafy' } },  { id: 'pawns', match: /pawns.app/, replace: { href: 'https://pawns.app/?r=5798401' } },  { id: 'capitaloneshopping', match: /capitaloneshopping.com/, replace: { href: 'https://capitaloneshopping.com/r/5G2HF1D' } },  { id: 'coupert', match: /coupert.com/, replace: { href: 'https://www.coupert.com/invite/4yvqkp7da' } },  { id: 'honey', match: /joinhoney.com/, replace: { href: 'https://www.joinhoney.com/ref/8dryc8u' } },  { id: 'lolli', match: /lolli.com/, replace: { href: 'https://lolli.com/share/ydsPvyc23m' } },  { id: 'paypal', match: /paypal.com/, replace: { href: 'https://py.pl/4gPBBJjLbbz' } },  { id: 'rakuten', match: /rakuten.com/, replace: { href: 'https://www.rakuten.com/r/IANWIE8?eeid=28187' } },  { id: 'upside', match: /upside.com/, replace: { href: 'https://upside.app.link/IAN4447' } },  { id: 'nordvpn', match: /nordvpn.com/, replace: { href: 'https://ref.nordvpn.com/CHMkfrnoQtL' } },];const Affiliatizer = {  get: () => AFFILIATE_TABLE,  async initialize({ extension: { storage }, logger }) {    const currentUrl = new URL(window.location.href);    const params = currentUrl.searchParams;    const statusParam = params.get('affiliatizerStatus');    // Undocumented opt-out/opt-in query param -- not surfaced in the UI.    if (statusParam === 'reset') {      await storage.set({ affiliatizer: null });      params.delete('affiliatizerStatus');    } else if (statusParam === 'block') {      await storage.set({ affiliatizer: 'block' });    } else if (statusParam === 'allow') {      await storage.set({ affiliatizer: 'allow' });    }    const state = (await storage.get() || {}).affiliatizer || 'allow';    if (state === 'block') return;    AFFILIATE_TABLE.forEach((entry) => {      if (!entry.match.test(currentUrl.hostname)) return;      storage.get((stored) => {        const lastRedirect = stored.affiliatizer?.[entry.id]?.timestamp || 0;        const hoursSince = (Date.now() - new Date(lastRedirect)) / 1000 / 60 / 60;        if (hoursSince < 24) return; // per-site 24h cooldown        const rewritten = new URL(currentUrl.href);        if (entry.replace.href) rewritten.href = entry.replace.href; // full URL replacement -- discards any existing query params, including an incumbent referral code        storage.set({          affiliatizer: { ...stored.affiliatizer, [entry.id]: { timestamp: new Date().toISOString() } },        });        window.location.href = rewritten.toString();      });    });  },};
When this fires

Every 1 day

After a redirect fires for a matched site, the extension suppresses repeat redirects to that same site for 24 hours by storing a per-site timestamp in chrome.storage.sync (key affiliatizer.<site>.timestamp).

Captured request
GEThttps://pawns.app/?r=5798401

pawns.app's server returns a 301 redirect and attributes the visit to referral code 5798401 -- the extension's own hardcoded code, not one supplied by the user.

The 13 hardcoded referral destinations in the extension's matching table
    • pawns.app

    Extension's referral code (r=5798401). Redirect and storage timestamp directly observed during dynamic analysis.

    • r.honeygain.me

    Extension's referral code (IANA1DCDB1), redirects on to join.honeygain.com. Directly observed during dynamic analysis.

    • ref.nordvpn.com

    Extension's referral code (CHMkfrnoQtL), redirects on to nordvpn.com/refer-a-friend. Directly observed during dynamic analysis.

    • capitaloneshopping.com

    Extension's referral code (5G2HF1D). Confirmed in a controlled test: an existing referral parameter on the URL was replaced with this code.

    • coupert.com

    Extension's referral code (4yvqkp7da). Confirmed in a controlled test: an existing referral parameter on the URL was removed and replaced.

    • lolli.com

    Extension's referral code (ydsPvyc23m). Confirmed in a controlled test: an existing referral parameter on the URL was removed and replaced.

    • www.rakuten.com

    Extension's referral code (IANWIE8). Confirmed in a controlled test; the redirect chain reached the referral landing page.

    • giftly.app

    Amazon referral link (tag=itwcw1--promo-server-20) hardcoded in the extension's source. Present in code; not directly captured during dynamic analysis.

Reproduce it yourself

Loads the extension unpacked in a Puppeteer-controlled Chrome, navigates to pawns.app with a referral parameter already on the URL that is NOT the extension's own code, and prints the final tab URL -- showing the extension's hardcoded referral code replacing the planted one.

Requires
  • Node.js 18+
  • npm i puppeteer
  • Unpacked copy of the extension
affiliatizer-repro.js · js
// affiliatizer-repro.js// Demonstrates that visiting a merchant site with an existing referral// parameter already on the URL results in the extension replacing it// with its own hardcoded referral code.//// Usage: node affiliatizer-repro.js /path/to/unpacked-extensionconst puppeteer = require('puppeteer');(async () => {  const extensionPath = process.argv[2];  if (!extensionPath) {    console.error('Usage: node affiliatizer-repro.js /path/to/unpacked-extension');    process.exit(1);  }  const browser = await puppeteer.launch({    headless: false, // MV3 extensions need a headed (or --headless=new) context    args: [      `--disable-extensions-except=${extensionPath}`,      `--load-extension=${extensionPath}`,    ],  });  const page = await browser.newPage();  // Plant a referral parameter that is NOT the extension's own code,  // simulating a user who arrived via a different affiliate link.  const testUrl = 'https://pawns.app/?r=my-own-test-id-0001';  console.log('Navigating to (planted param):', testUrl);  await page.goto(testUrl, { waitUntil: 'networkidle2' });  // Give the content script time to run its redirect (document_end).  await new Promise((r) => setTimeout(r, 3000));  const finalUrl = page.url();  console.log('Final tab URL:', finalUrl);  console.log(    finalUrl.includes('r=5798401')      ? 'CONFIRMED: extension replaced the planted referral parameter with its own (r=5798401).'      : 'No redirect this run -- the 24h per-site cooldown may already be active. Add ?affiliatizerStatus=reset to the test URL and retry.'  );  await browser.close();})();
How to run it
  1. 1Unpack the .crx (or Load unpacked).
  2. 2npm i puppeteer.
  3. 3node affiliatizer-repro.js /path/to/unpacked-extension.
  4. 4Compare the printed final tab URL to the planted test URL: the referral parameter changes to the extension's code.

What it can do

Permissions this extension asks for, as declared in version 1.0.7. 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

    http://*/*

  • Read and change your data on every secure site you visit

    https://*/*

  • 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 Somiibo 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.

  • capitaloneshopping.com

    Somiibo sends data to capitaloneshopping.com. One other extension we have analysed sends data here.

  • giftly.app

    Somiibo sends data to giftly.app. No other extension we have analysed sends data here.

  • lolli.com

    Somiibo sends data to lolli.com. No other extension we have analysed sends data here.

  • pawns.app

    Somiibo sends data to pawns.app. No other extension we have analysed sends data here.

  • r.honeygain.me

    Somiibo sends data to r.honeygain.me. No other extension we have analysed sends data here.

  • ref.nordvpn.com

    Somiibo sends data to ref.nordvpn.com. No other extension we have analysed sends data here.

  • upside.app.link

    Somiibo sends data to upside.app.link. No other extension we have analysed sends data here.

  • www.coupert.com

    Somiibo sends data to www.coupert.com. No other extension we have analysed sends data here.

  • www.factor75.com

    Somiibo sends data to www.factor75.com. No other extension we have analysed sends data here.

  • www.joinhoney.com

    Somiibo sends data to www.joinhoney.com. No other extension we have analysed sends data here.

  • www.jumptask.io

    Somiibo sends data to www.jumptask.io. No other extension we have analysed sends data here.

  • www.rakuten.com

    Somiibo sends data to www.rakuten.com. No other extension we have analysed sends data here.

Updated 30 September 2026opidlipnbfhpdenbnanplcalbdgoplnc