Is Offer.love - Bank Merchant Card Offer Collector safe?

Medium risk

Offer.love uploads collected bank card-offer details to api.offer.love every six hours.

When you trigger its bank offer collectors, the extension stores offer records that can include merchant and domain details, offer titles, dates, card numbers or images, bank/account labels or IDs, and session or recommendation tokens. A background alarm sends the stored personal offer catalog to api.offer.love/offers/log every six hours.

Costbellv1.17.2Chrome Web Store
45Risk
Who publishes it

Costbell - 1 other listing from the same operator, 1 of them carrying a finding

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

Publisher
Costbell

Same store account

1 other listing published from this account, 4k+ users between them. 1 of them carries a finding.

Shared hosts - 1 hostname

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.

onlinebanking.usbank.com
Also called by 6 other listings, including CardPointers, CardPointers X

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

Publishers can request a review.

Findings

Offer.love uploads your saved bank card offers to its servers every 6 hours

Collecting offers from a bank/merchant page (Amex, Chase, BofA, Citi, PayPal, US Bank, or a coupon page) stores them locally.

Every 6 hours, a cron alarm uploads your offer history to Offer.love: merchant, title, card number, and bank.

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

You click Start in the extension popup on a supported bank or merchant offers page.

Supported sites include American Express, Chase, Bank of America, Citi, PayPal, US Bank, and several grocery-store coupon pages.

The extension did this

The extension saves every visible offer record, then automatically uploads your entire saved offer history to Offer.love's own server every 6 hours.

The upload runs on a background alarm with no additional prompt or confirmation at send time.

When this fires

Every 6 hours

Every 6 hours, whether or not you've added any new offers since the last cycle, the background alarm re-sends the entire local offer store.

Fields observed in each uploaded offer record
  • Merchant / offer title
    $50 back on $200+ at Peloton

    Which offer or merchant the record is for.

  • Site domain
    chase.com

    Which bank or merchant site the offer came from.

  • Card number (masked)
    ••••4821

    The last few digits of the card the offer is tied to, as returned by your bank's own page.

  • Bank name
    Chase

    Which financial institution the offer and card belong to.

  • Account label
    Chase Freedom Unlimited

    The nickname your bank uses for the account tied to the card, included for some banks.

  • Offer / session token (US Bank only)
    serveToken=8f2ac91b..., sessionTokenId=a91cd44e...

    For US Bank offers, the record also includes the bank's own offer-activation token and session token ID, not just the offer's contents.

Captured request
POSThttps://api.offer.love/offers/log?key=offer-love-chrome-extension

HTTP 200, empty response body.

Headers
Content-Type
application/json
Body
{"chase.com":[{"merchantName":"Peloton","title":"$50 back on $200+","details":"Get $50 statement credit when you spend $200 or more","cardNumber":"••••4821","bank":"Chase","accountLabel":"Chase Freedom Unlimited","offerId":"8f2ac91b-4d3e-4a11-9c02-114fbb2a9dd7","startedAt":1755000000000,"expiresAt":1758000000000}]} (illustrative)
The code that does this

Upload alarm handler, and a bank session token folded into the same record

Readable version

Readable alarm handler

background.js
chrome.alarms.onAlarm.addListener(async (alarm) => {  if (alarm.name === "cron-offer-upload") {    const { offersData } = await getOffersPersonal(); // reads the entire local store    if (Object.keys(offersData).length > 0) {      fetch("https://api.offer.love/offers/log?key=offer-love-chrome-extension", {        method: "POST",        headers: { "Content-Type": "application/json" },        body: JSON.stringify(offersData), // uploads every saved offer, for every bank      });    }  }});

Readable US Bank offer object

usbank/usbank.js
// offerRecord already carries offerId, serveToken, and sessionTokenId// returned by US Bank's own offer-activation APIawait activateOffer(offerRecord.offerId, offerRecord.serveToken, offerRecord.sessionTokenId);await storeOfferData(offerRecord); // the same object, tokens included, is queued for upload
Where your offer data goes
    • api.offer.love

    Receives your entire local offer store every 6 hours: masked card numbers, bank names, account labels, and (US Bank) live activation tokens.

Where it sends data

Destinations our analysis observed Offer.love - Bank Merchant Card Offer Collector 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.offer.love

    Offer.love - Bank Merchant Card Offer Collector sends data to api.offer.love. No other extension we have analysed sends data here.

Updated 30 September 2026onoiombdhkjneegnlbgodhopdnadfknm