Is InsTF - Instagram follower & unfollower tracker safe?

Medium risk

InsTF sends the signed-in user's Google email address and Instagram profile statistics to Mixpanel on account sign-in and follower-tracking task execution.

When a user signs in via Google OAuth, the extension forwards their email address and membership status to Mixpanel's People API, linked to a persistent UUID stored in chrome.storage.sync. Each time the user runs a follower-tracking task against their own Instagram account, it also sends their Instagram username, follower count, following count, and media count to Mixpanel. Task lifecycle events — including the target Instagram account ID and task type — are transmitted to api-js.mixpanel.com on task start and completion.

Neo Ext Teamv6.1.13Chrome Web Store
45Risk

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

Publishers can request a review.

Findings

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-359
SourceAI SANDBOX

Google email and Instagram task data sent to Mixpanel

After Google sign-in and follower-tracking actions, code shows the extension attaches your email, membership fields, Instagram stats, and download counts to a Mixpanel profile/event.

Captured POSTs only showed page-view/profile analytics.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You sign in with Google or start an Instagram follower-tracking task.

Download actions from scraped Instagram results also trigger analytics events.

The extension did this

The extension adds account, profile, task, and count fields to Mixpanel profile updates or event calls.

The sensitive sign-in and task fields are shown in code; the available captured Mixpanel traffic did not include those fields.

02EvidenceFIELD TABLE
Fields the shipped code passes to Mixpanel
FieldValueWhy it matters
Analytics identifier
6fce7a7d-4c0e-4e5b-9bc6-6b0dc81db0e2 (illustrative)Lets Mixpanel tie future sign-in, task, and download events to the same browser profile.
Google account email
alex.rivera@example.com (illustrative)Identifies the Google account used to sign in to the extension.
Membership record
membership: Pro; is_yearly: true; starts_at: 2026-01-15T00:00:00.000Z; ends_at: 2027-01-15T00:00:00.000Z (illustrative)Adds subscription context to the same analytics profile.
Instagram profile statistics
username: alexruns; media_count: 92; follower_count: 1842; following_count: 730; profile_url: https://www.instagram.com/alexruns/ (illustrative)Links your Instagram username and follower counts to the analytics profile when you track your own account.
Task target and settings
target: 17841400001234567; actionType: getProfile; loopType: follower; total: 250 (illustrative)Shows which Instagram account or list the extension was asked to process and how the task was configured.
Downloaded contact counts
filter: email; total: 250; emailCount: 18; phoneCount: 4 (illustrative)Summarizes how many scraped profiles had email or phone fields in the downloaded result set.
03EvidenceNETWORK CAPTURE
Captured request
POSThttps://api-js.mixpanel.com/track
Observed during dynamic analysis from www.listmore.info; the recorded body contained page-view token/current_url analytics, not the sign-in or task fields shown in code.
04EvidenceNETWORK CAPTURE
Captured request
POSThttps://api-js.mixpanel.com/engage
Observed during dynamic analysis from www.listmore.info; the recorded body contained profile set-once token/current_url analytics, not the sign-in or task fields shown in code.
05EvidenceCODE COMPARE
The code that does this

Mixpanel setup, profile updates, task events, and download events

What it actually does
Persistent Mixpanel identifier in deobfuscated codedist/contentScripts/index.global.js
async function MV() {
  let t = (await it.storage.sync.get("MIXPANEL_USER_ID")).MIXPANEL_USER_ID;
  return t || (t = globalThis.crypto.randomUUID(), await it.storage.sync.set({
    MIXPANEL_USER_ID: t
  })), t
}
Mixpanel token, identify, and first-seen update in deobfuscated codedist/contentScripts/index.global.js
const Vk = {
    InsTF: {
      mixpanel_token: "8f728f9dda62790d6831ca89119dee88",
      sentry_DSN: "https://9d1a7261a888a4a542c01ad9396072b8@o4507079421394944.ingest.us.sentry.io/4507079424081920"
    }
  },
  qk = Vk.InsTF.mixpanel_token;
async function XG() {
  try {
    _r.init(qk, {
      debug: !1,
      persistence: "localStorage"
    }), _r.register({
      ext_name: "InsTF",
      ext_version: "6.1.11"
    });
    const e = await MV();
    _r.identify(e), _r.people.set_once({
      "First Seen": new Date().toISOString()
    })
  } catch (e) {
    console.error("Failed to initialize Mixpanel:", e)
  }
}
XG();
Google sign-in profile fields sent to Mixpanel in deobfuscated codedist/contentScripts/index.global.js
async function a() {
  try {
    o.value = !0;
    const w = await nA("launch-web-auth-flow", {
        url: n.href
      }),
      b = new URL(w.redirectedTo),
      E = new URLSearchParams(b.hash.substring(1)),
      {
        data: T,
        error: k
      } = await s.auth.signInWithIdToken({
        provider: "google",
        token: E.get("id_token") || ""
      });
    if (k) throw k;
    {
      fs("signInWithGoogle", T.user);
      const S = T.user;
      await l({
        id: S.id,
        email: S.email,
        full_name: S.user_metadata.full_name
      }), ["InsC", "InsGrow", "InsFo"].includes("InsTF") && await u()
    }
  } catch (w) {
    fs("signInWithGoogle catch error", w, it.runtime.lastError)
  } finally {
    o.value = !1
  }
}
async function l(w) {
  const {
    data: b,
    error: E
  } = await s.from("InsTF").upsert({
    ...w
  }, {
    onConflict: "id"
  }).select().single();
  E && (console.error(`createOrUpdateSupabaseUser error: ${JSON.stringify(E)}`), s.auth.signOut(), lt.value = {}), fs("createOrUpdateSupabaseUser", b), lt.value = b, b.created_at || await s.from("InsTF").update({
    created_at: new Date().toISOString()
  }).eq("id", b.id), _r.people.set({
    email: b.email,
    membership: b.membership,
    is_yearly: b.is_yearly,
    starts_at: b.starts_at,
    ends_at: b.ends_at
  })
}
Task profile stats and task object sent to Mixpanel in deobfuscated codedist/contentScripts/index.global.js
Rt(async () => {
  const g = PV(),
    p = g.uuid;
  r.value = (await it.storage.local.get(p))[p], await d(l.value);
  async function m() {
    const x = Wn.getMyId();
    if (!x) return _r.track("Not Login", {
      profileId: x
    }), !1;
    const y = (await it.storage.local.get("trackMySelfInfo")).trackMySelfInfo || {};
    if (x !== y.id) {
      const w = await Wn.getProfile(x);
      await it.storage.local.set({
        trackMySelfInfo: {
          id: w.id,
          username: w.username
        }
      }), y.id = w.id, y.username = w.username
    }
    return r.value.username === y.username
  }
  async function _() {
    return await m() ? (n.value = !0, await Wn.getProfile(Wn.getMyId())) : await Wn.getProfile(r.value.username, "username")
  }
  if (!r.value.target && r.value.username) try {
    const x = await _();
    r.value.target = x.id, r.value.profile = x, o.value.unshift(p), a.value.unshift(r.value), await it.storage.local.set({
      [p]: r.value,
      [l.value]: [...o.value]
    })
  } catch (x) {
    Gp(x, {
      ...r.value,
      isTrackMySelf: n.value
    });
    return
  }
  if (fs("trackTask", r.value), n.value) {
    const x = r.value.profile;
    _r.people.set({
      username: x.username,
      media_count: x.media_count,
      follower_count: x.follower_count,
      following_count: x.following_count,
      profile_url: x.profile_url
    })
  }
  _r.track("Task Start", {
    ...r.value
  }), c.value = u.value.length === 0, g.isFirstTrack && (c.value = !0)
});
async function f() {
  r.value.isCompleted = !0, await it.storage.local.set({
    [r.value.uuid]: r.value
  }), await d(l.value), _r.track("Task Completed", {
    ...r.value
  })
}
Download event counts sent to Mixpanel in deobfuscated codedist/contentScripts/index.global.js
function c(g) {
  const p = ["email", "phone"].includes(g) ? l(g) : r.items;
  a(p, n.value), _r.track("Download", {
    target: r.target,
    loopType: r.loopType,
    actionType: r.actionType,
    format: n.value,
    filter: g,
    total: r.items.length,
    emailCount: p.filter(m => m.email).length,
    phoneCount: p.filter(m => m.phone).length
  })
}
function u() {
  a(r.items, n.value), _r.track("Download", {
    target: r.target,
    loopType: r.loopType,
    actionType: r.actionType,
    format: n.value,
    total: r.items.length
  })
}
function h() {
  if (d.value) {
    const g = NV(r.items);
    a(g, n.value, `${i.value}-distinct-${g.length}`), _r.track("Download", {
      target: r.target,
      loopType: r.loopType,
      actionType: r.actionType,
      format: n.value,
      total: g.length
    })
  } else u();
  f.value = !1
}
06EvidenceTHIRD PARTY LIST
Analytics destinations observed or configured by the extension
  • api-js.mixpanel.com

    Mixpanel analytics API receiving profile updates and tracked events from the extension code.

  • o4507079421394944.ingest.us.sentry.io

    Sentry error-reporting endpoint configured next to the Mixpanel token; not the destination for the Mixpanel profile and task events in this claim.

Data recipients

api-js.mixpanel.com
Updated 17 September 2026deppcpikimfefmjmdpalknbdfmhdlein