Is Minea safe?

Medium risk

Minea reads Facebook profile data (ID, name, city, birthday, gender) while browsing the Ads Library and sends it to data.minea.com.

When a user visits the Facebook Ads Library, Minea intercepts GraphQL responses via a monkey-patched XHR hook and collects the authenticated user's profile details — including city, hometown, address, birthday, and gender — by fetching the user's mbasic Facebook profile page from the extension's background context. The collected PII and ad feed data are base64-encoded and posted to data.minea.com/v2/tokens using hardcoded Basic Auth credentials embedded in the extension bundle.

Mineav1.3.2Chrome Web Store
49Risk
Who publishes it

Minea - 1 other listing from the same operator, none carrying a finding

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

Publisher
Minea

Same store account

1 other listing published from this account, 20k+ users between them, none of them carrying a finding.

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

Publishers can request a review.

Findings

Hardcoded Minea API credential shipped in the extension bundle

MediumunwantedCWE-522Dynamic sandbox

The extension ships a fixed username/password in its JavaScript, sent as a Basic-auth header to data.minea.com.

What actually happens

You did this

You browse the Facebook Ads Library with the extension active.

No login or per-user setup creates this credential; it is already baked into the shipped code.

The extension did this

The extension POSTs to data.minea.com using a fixed Basic-auth credential embedded in its JavaScript.

The same username:password pair is attached for every user on every install.

Captured request

POSThttps://data.minea.com/v2/tokens

Returns a JSON token response which is passed back to the caller.

Headers
Content-Type
application/json
Authorization
Basic <redacted> (base64 of dropispy:<redacted>)
Body
<message-supplied data payload>

The code that does this

The static credential is constructed inline in the background service worker.

Readable version
if (msg.action === "sendTokens") {  fetch("https://data.minea.com/v2/tokens", {    method: "POST",    body: msg.params.data,    headers: {      "Content-Type": "application/json",      // Same username:password for every install, only base64-encoded      Authorization: "Basic " + btoa("dropispy:gzK@8s6DVyVr")    }  });}

Check if you're affected

Recovers the embedded Basic-auth username:password pair from the extension's Authorization header, demonstrating that the credential is readable by anyone who has the extension.

Requires
  • Node.js 18+
decode-minea-cred.js · js
// Decode the Basic-auth header the extension sends to data.minea.com.// The header value is base64 of 'username:password'.const headerValue = 'ZHJvcGlzcHk6Z3pLQDhzNkRWeVZy'; // from Authorization: Basic <value>const decoded = Buffer.from(headerValue, 'base64').toString('utf8');console.log('Embedded credential (user:pass):', decoded);// To find it directly in source instead://   grep -o "btoa(\"[^\"]*\")" static/background/index.js
How to run it
  1. 1Save this file as decode-minea-cred.js.
  2. 2Run: node decode-minea-cred.js.
  3. 3Observe the username:password pair printed; it is the same for every installation.

Why a base64 header is not protection

Basic authentication encodes the credential with base64 purely so it survives transport in an HTTP header. base64 is reversible with no key, so the username and password are recoverable by anyone who can read the request or the shipped source. A credential that is identical across all installs identifies the vendor's client, not the individual user.

Service worker reads your Facebook profile city, address, birthday, gender

MediumunwantedCWE-200Dynamic sandbox

While browsing Facebook Ads Library, the background worker fetches mbasic.facebook.com using your session: the home page for your username, then '/about', parsed for city, address, birthday, gender.

What actually happens

You did this

You browse the Facebook Ads Library while logged in to Facebook.

No prompt asks to read your own profile; the fetch happens in the background.

The extension did this

The extension's service worker fetches your mbasic.facebook.com profile using your active Facebook session.

It reads your name from the mbasic home page, then loads your /about page.

Captured request

GEThttps://mbasic.facebook.com/

Returns the mbasic home HTML; the extension reads the username from the page navigation. Requests to mbasic.facebook.com from the service worker (chrome-extension context) were observed during dynamic analysis.

Headers
Origin
chrome-extension://gklhghenemaeogngbnjdheklnnonajoc

The code that does this

Background handlers fetch mbasic.facebook.com in the extension context and return raw HTML.

Readable version
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {  if (msg.action === "getMbasicFBIndex") {    fetch("https://mbasic.facebook.com/")      .then(r => r.text()).then(html => sendResponse(html));  }  if (msg.action === "getAboutPage") {    fetch("https://mbasic.facebook.com/" + msg.params.user_full_name + "/about")      .then(r => r.text()).then(html => sendResponse(html));  }  return true;});

Profile fields parsed out of the returned /about HTML

  • Current city
    Austin, Texas

    Where you currently live, as listed on your Facebook profile.

  • Address
    123 Maple Ave

    Your address field from the profile, when present.

  • Home town
    Dallas, Texas

    The hometown listed on your profile.

  • Birthday
    March 14, 1990

    Your date of birth from the profile.

  • Gender
    Female

    The gender field listed on your profile.

  • Name
    Jane Doe

    Your profile name, derived from the mbasic page navigation.

The code that does this

The content script selects each field out of the about-page HTML.

Readable version
const getCity     = html => $(html).find('td:has(a[href*="edit=current_city"]) ~ td a').text();const getAddress  = html => $(html).find('td:has(a[href*="edit=address"]) ~ td a').text();const getBirthday = html => $(html).find('td:has(a[href*="edit=birthday"]) ~ td div').text();const getGender   = html => $(html).find('td:has(a[href*="edit=gender"]) ~ td div').text();// Assembled into { id, city, home_town, address, birthday, gender, name }chrome.runtime.sendMessage({ action: "getAboutPage", params: { user_full_name } }, html => {  const profile = { city: getCity(html), address: getAddress(html),                    birthday: getBirthday(html), gender: getGender(html) };});

Where it sends data

Destinations our analysis observed Minea 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.

  • data.minea.com

    Minea sends data to data.minea.com. One other extension we have analyzed sends data here.

  • mbasic.facebook.com

    Minea sends data to mbasic.facebook.com. One other extension we have analyzed sends data here.

Updated 30 September 2026gklhghenemaeogngbnjdheklnnonajoc