Is Pie Shopping: AI Cash Back and Coupons safe?

Medium risk

Pie Shopping is medium risk. Pie Shopping's signed-in chat flow can collect offer IDs and POST them to zeroclick.dev/api/v2/impressions. The bundled ZeroClick SDK preps offer requests with user agent, origin, IP, and identity fields. DA didn't reach the logged-in path.

Pie Extensionsv1.33.1Chrome Web Store
50Risk
Who publishes it

The People's Internet Experiment (pie.org) - 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
Pie Extensions
Declared legal entity
The People's Internet Experiment (pie.org)
Registered address
13800 Bora Bora Way, Marina Del Rey, CA 90292-6803, US

Same store account

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

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

bathandbodyworks.com
Also called by 1 other listing: Swash
cart.godaddy.com
Also called by 1 other listing: ProCouponCode Autopilot: Online Coupon Codes
buyagift.co.uk
Also called by 2 other listings, including AskmeOffers AI: Automatically Applies Coupons, Promo Codes & Offers
catherines.com
Also called by 2 other listings, including AskmeOffers AI: Automatically Applies Coupons, Promo Codes & Offers
checkout.prettylittlething.com
Also called by 2 other listings
checkout.prettylittlething.fr
Also called by 2 other listings, including AskmeOffers AI: Automatically Applies Coupons, Promo Codes & Offers
fitflop.com
Also called by 2 other listings
hammacher.com
Also called by 2 other listings
loft.com
Also called by 2 other listings
puritan.com
Also called by 2 other listings, including AskmeOffers AI: Automatically Applies Coupons, Promo Codes & Offers
carid.com
Also called by 3 other listings
marshalls.com
Also called by 3 other listings, including ADM Crosslister
prettylittlething.com
Also called by 3 other listings
prettylittlething.fr
Also called by 3 other listings

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

Publishers can request a review.

Findings

Pie Shopping sends chat offer IDs to ZeroClick

Pie Shopping's signed-in chat flow can collect offer IDs and POST them to zeroclick.dev/api/v2/impressions.

The bundled ZeroClick SDK preps offer requests with user agent, origin, IP, and identity fields.

DA didn't reach the logged-in path.

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

You use Pie Shopping's signed-in chat assistant and receive a response containing sponsored offer parts.

The code path is tied to chat parts named data-ui-offers, data-ui-top-merchants, and data-ui-products.

The extension did this

The extension collects ZeroClick offer impression IDs and passes them to its bundled reporting SDK.

The SDK constructs a POST request for the ZeroClick impressions endpoint.

Fields visible in the ZeroClick code paths
  • Offer impression ID
    offer_01J1A9Z8M2K7Q3D5F6G8H9J0 (illustrative)

    Lets the offer provider know which sponsored offer was shown in your chat result.

  • Browser user agent
    Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 (illustrative)

    Describes your browser and operating system to the offer provider.

  • Origin page context
    https://www.target.com/c/kitchen-dining (illustrative)

    Can connect the sponsored offer request to the shopping page or chat context that produced it.

  • Network address
    198.51.100.24 (illustrative)

    The destination server can see the network address used for the request, which can approximate location or organization.

  • Optional identity fields
    userSessionId: sess_9f4c21a7d8e3 (illustrative)

    If provided to the SDK, these fields can tie offer requests to an account, hashed contact detail, session, or locale.

Captured request
POSThttps://zeroclick.dev/api/v2/impressions

The request shape is constructed by the shipped SDK; dynamic analysis did not capture a live response because the chat path remained behind the Pie login wall.

Headers
Content-Type
application/json
X-ZeroClick-SDK-Version
0.1.0
The code that does this

The SDK builds the ZeroClick POST and the chat UI feeds it offer IDs

Readable version

Readable API client

deobfuscated/sidePanel.js
function An(e) {  let {    apiKey: n,    baseUrl: t  } = e;  return {    post: async function(e, r, o) {      let i = `${t}${e}`,        a = function(e) {          let n = {            "Content-Type": "application/json",            "X-ZeroClick-SDK-Version": "0.1.0"          };          e && (n["x-zc-api-key"] = e);          let t = function() {            if (typeof navigator < "u" && navigator.userAgent) return navigator.userAgent          }();          return t && (n["X-ZeroClick-User-Agent"] = t), n        }(o?.authenticate ?? 1 ? n : void 0),        s = await fetch(i, {          method: "POST",          headers: a,          body: JSON.stringify(r)        });      if (!s.ok) throw new kn(await async function(e) {        try {          let n = await e.json();          return {            message: n.error?.message ?? n.message ?? "An unknown error occurred",            status: e.status          }        } catch {          return {            message: e.statusText || "An unknown error occurred",            status: e.status          }        }      }(s));      if (204 !== s.status) return s.json()    }  }}

Readable impression tracker

deobfuscated/sidePanel.js
static async trackOfferImpressions(n) {  if (e.ensureInitialized(), !n || 0 === n.length) throw Error("ZeroClick: ids array cannot be empty");  await e.apiClient.post("/api/v2/impressions", {    ids: n  }, {    authenticate: !1  })}

Readable chat-part collector

deobfuscated/sidePanel.js
(0, e.useEffect)((function() {  var e, n, t, r, o = c[c.length - 1];  if (c.length || w.current.clear(), o) {    var i = o.parts.filter((function(e) {      return "data-ui-prompts" === e.type    })).find((function(e) {      var n;      return "success" === (null === (n = e.data) || void 0 === n ? void 0 : n.status)    }));    i && (null === (n = null === (e = i.data) || void 0 === e ? void 0 : e.prompts) || void 0 === n ? void 0 : n.length) ? v(i.data.prompts) : v([]);    var a = new Set,      s = null === (t = o.parts) || void 0 === t ? void 0 : t.filter((function(e) {        return "text" === e.type      })).map((function(e) {        return e.text      })).join("");    null === (r = o.parts) || void 0 === r || r.forEach((function(e) {      var n, t, r;      if ("data-ui-offers" === e.type) {        var o = (null === (n = e.data) || void 0 === n ? void 0 : n.offers) || [];        O(o), o.forEach((function(e) {          e.aiOfferId && s.includes(e.clickUrl) && a.add(e.aiOfferId)        }))      }      "data-ui-top-merchants" === e.type && (o = (null === (t = e.data) || void 0 === t ? void 0 : t.offers) || [], O(o), o.forEach((function(e) {        e.aiOfferId && a.add(e.aiOfferId)      }))), "data-ui-products" === e.type && (o = (null === (r = e.data) || void 0 === r ? void 0 : r.products) || [], O(o), o.forEach((function(e) {        e.aiOfferId && a.add(e.aiOfferId)      })))    }));    var l = Array.from(a).filter((function(e) {      return !w.current.has(e)    }));    l.length > 0 && (l.forEach((function(e) {      return w.current.add(e)    })), T(l))  }  p()}), [c, O, T])
The code that does this

The extension bundle contains the ZeroClick host and API key

Readable version

Readable production constants

deobfuscated/background.js
const t = {  NODE_ENV: "production",  BUILD_ENV: "production",  VERSION: "1.33.6",  APP_NAME: "@piedotorg/extension",  EXTENSION_TYPE: "shopping",  PLATFORM: "ch",  SEGMENT_WRITE_KEY: "cuVYSvijPDykxOEOXeDMZp7nA9zyFxFF",  BROWSER_TARGET: "chrome",  SLEEK_API_KEY: "b88024fa0f76d7fd23fedfb14f53229b0a4a8e4851d3e3d9",  ZEROCLICK_API_KEY: "pd2hD-6QllX1nNCmmtDLOrEb60rJzGn0GcSwzYrDvdc"}.APP_ID;

Readable runtime hosts

deobfuscated/sidePanel.js
const Pm = "https://zeroclick.dev",  Lm = "https://www.pie.org",  Om = "https://chat.pie.org/api/v1";
External hosts involved in this flow
    • zeroclick.dev

    Receives the SDK's offer and impression API requests for sponsored chat offers.

    • chat.pie.org

    Supplies the Pie shopping assistant chat responses whose sponsored offer parts feed the impression tracker.

    • www.pie.org

    Provides the login cookie checked before the chat path becomes reachable.

Dynamic-analysis caveat

Dynamic analysis reached Pie's login wall and did not observe any requests to zeroclick.dev or chat.pie.org. The confirmed evidence for this claim is the shipped code path: the login check looks for an is-logged-in cookie, and without a valid Pie session the chat flow that feeds ZeroClick impression tracking was not reachable.

What it can do

Permissions this extension asks for, as declared in version 1.33.6. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to. The current listed version is 1.33.1, which we have not unpacked yet.

  • Read and change your data on every site you visit

    <all_urls>

  • Schedule its own background tasks

    alarms

  • Read and change cookies, including the ones that keep you signed in

    cookies

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

    tabs

  • Store data in your browser

    storage

  • Run its own code inside the pages you visit

    scripting

  • See every page you navigate to, as you navigate to it

    webNavigation

  • Store an unlimited amount of data in your browser

    unlimitedStorage

  • See which of your requests its blocking rules matched

    declarativeNetRequestFeedback

  • Run hidden pages in the background

    offscreen

  • Watch every request your browser makes

    webRequest

  • See, disable and uninstall your other extensions, including your security ones

    management

  • Show a panel beside the page

    sidePanel

declarativeNetRequestWithHostAccess
Updated 30 September 2026nfadicbbecgbdbgbibgflooojfbolpgk