Is WABiz Bulk Sender safe?
WABiz Bulk Sender transmits message content, recipient phone numbers, and Google account credentials to its vendor servers on every use.
Each time a message is sent, the extension POSTs the full message text and recipient phone numbers to wabiz.in. When the popup opens, it reads the signed-in Google account email, name, and a device ID and sends them to the same backend for license validation. The extension also writes the user's WhatsApp phone number and display name as cookies on wabiz.in, and logs contact list metadata to a Firebase Cloud Functions endpoint when contacts are exported.
Who publishes itWA Biz Sender - no other listings under this identity, 2 shared hostnames
WA Biz Sender - no other listings under this identity, 2 shared hostnames
What this publisher told the store about itself, and the other listings that told it the same thing.
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.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
WhatsApp message text and recipients sent to WABiz
Sending WhatsApp messages through WABiz sends message text, recipient numbers, user ID, and version to wabiz.in stats endpoints.
Single sends post to /stats/singlemsg; bulk sends also post recipients, messages, and completion report.
What actually happens
You click send for a single WhatsApp message or start a bulk message run.
The send flow includes the message text you typed and the phone numbers selected for delivery.
The extension posts those send details to wabiz.in stats endpoints.
The source code passes single-message text and numbers directly, and bulk sends include taskData with numbers and messages arrays.
Fields sent by the message stats code
- Message textHi Jordan, your appointment is confirmed for 3 PM today.
This is the WhatsApp message you typed or generated from a template.
- Recipient phone number+15551234567
This identifies who you are contacting through the extension.
- Extension user ID9f4c1a22-73d6-4a3a-a1d7-0e4b52793c81
This lets the backend connect the message activity to your extension account or license record.
- Extension version2.0.32
This adds context about the exact extension build used for the send.
- Bulk send reportSent / Failed / Pending status for +15551234567
This records which recipients were sent, skipped, failed, or still pending during a bulk run.
Captured request
Request body schema is defined in shipped source; traffic analysis did not capture a live single-message send body.
- Content-Type
- application/json
Captured request
Request body schema is defined in shipped source; traffic analysis did not capture a live bulk-send body.
- Content-Type
- application/json
Captured request
Request body schema is defined in shipped source; traffic analysis did not capture a live completion-report body.
- Content-Type
- application/json
The code that does this
Shipped code paths that collect message data and post it to wabiz.in
Bulk-send task assembly
deobfuscated/popup/send-message.jsasync function n() { let e = [], n = []; var t = {}; if (B())(e = M).forEach(() => { n.push(getCustomizedMessage(0)) }); else { e = D(); var o = await h.getExcelFileData(); if (o) { var r = await h.getActiveSheet(); let a = await h.getStartIndex(), s = await h.getFinalIndex(); t.usingExcel = !0, o.sheets[r].rows.forEach((e, t) => { t >= a && t <= s && n.push(getCustomizedMessage(t)) }) } else await h.getCurrentMessageBulk(), e.forEach(() => { n.push(getCustomizedMessage(0)) }); try { var a = getVariablesInMessage().filter(e => e !== templatesControl.OPTOUT_VARIABLE_NAME); t.msgPersonalization = !!a?.length } catch (e) { console.log("Error in setting personalization:", e) } } m = !0, await U(), g = !1, S = OPERATION_SEND_MESSAGE, P = e.length, f = 0, _ = 0, s = oldAttchmentControl.getIsAttachmentSelected() ? oldAttchmentControl.getAttachment() : null, C = oldAttchmentControl.getAttachmentCount(), T = !1, await I(), i.updateView(), excelFileJSON && !B() && (t.fileName = fileName.split(".").slice(0, -1).join(".")), t.authid = authid, t.numbers = e, t.messages = n, t.contact = await void 0, l && isPro ? (t.messageGap = c, t.randomizeDelay = d) : (t.messageGap = 0, t.randomizeDelay = !1), b && isPro ? (t.batchGap = u, t.batchSize = p || e.length) : (t.batchGap = 0, t.batchSize = e.length), t.startTime = Date.now(), t.attachment = !!attachmentControl.getCount(), t.isCaption = !!attachmentControl.getIsCaption(), t.isPro = isGoldorSilver(), t.version = manifestData.version, analyticsInstance.logBulkMessageDetail(authid, t), await x(), t.tabid = await getActiveTab(), sendMsgToExtension({ from: POPUP_JS, subject: MSG_SETUP_BATCH, data: t })}Single-send click handler
deobfuscated/popup/send-message.js$("#sendMessageBulk").click(async function() { var e, t, a, s; !isPro && isMsgTemplate() ? alertControl.showAlertProFeatureMsgCustomization() : B() ? ($("#sendMessageBulkWrapper").addClass("disabled is-loading"), await n()) : 1 === (e = D()).length ? (t = await void 0, a = getCustomizedMessage(0), s = e[0], analyticsInstance.logSingleMsgDetail(authid, a, s), sendMsgToActiveTab({ from: POPUP_JS, subject: MSG_SEND_MESSAGE, data: { message: a, number: s, isAttachment: !!attachmentControl.getCount(), isCaption: !!attachmentControl.getIsCaption(), contact: t } })) : 0 < e.length && ($("#sendMessageBulkWrapper").addClass("disabled is-loading"), await n())})Stats POST methods
deobfuscated/common/analytics.jslogSingleMsgDetail: async function(e, t, n) { console.log("manifestData", s), await fetch("https://wabiz.in/stats/singlemsg", { method: "POST", mode: "cors", cache: "no-cache", credentials: "same-origin", headers: { "Content-Type": "application/json" }, redirect: "follow", referrer: "no-referrer", body: JSON.stringify({ message: t, phoneNumber: n, userid: e, version: s?.version }) })},logBulkMessageDetail: async function(e, t) { await fetch("https://wabiz.in/stats/bulkmsg", { method: "POST", mode: "cors", cache: "no-cache", credentials: "same-origin", headers: { "Content-Type": "application/json" }, redirect: "follow", referrer: "no-referrer", body: JSON.stringify({ userid: e, taskData: t }) })}Completion-report POST
deobfuscated/background/message-dispatcher.jsasync function C(e) { try { await fetch(ROOT_URL + "/stats/reports-completion", { method: "POST", mode: "cors", cache: "no-cache", credentials: "same-origin", headers: { "Content-Type": "application/json" }, redirect: "follow", referrer: "no-referrer", body: JSON.stringify({ data: { ...e, endTime: Date.now() }, authid: i }) }) } catch (e) { console.error("Failed to send completion report:", e) }}External destination for the message stats requests
- wabiz.in
Receives single-message stats, bulk-message task details, and bulk completion reports from WABiz Bulk Sender.
WhatsApp Contact Export Metadata Sent to Firebase
Exporting WhatsApp contacts builds the spreadsheet locally, then posts export metadata to a Firebase Cloud Functions endpoint: account identifier and selected contact sources, including counts and the chosen group, label, or broadcast-list.
What actually happens
You export WhatsApp contacts through the extension.
The popup sends the selected contact sources to the active WhatsApp tab.
The extension sends export metadata to a Firebase Cloud Functions endpoint.
The metadata is posted after the spreadsheet is written.
Fields assembled for the contact-download metadata request
- WhatsApp account identifieruserid: +14155550132 (illustrative)
Links the contact-export event to the WhatsApp account using the extension.
- Contact countcontactCount: 125 (illustrative)
Shows how many contacts were included in the export action.
- Selected contact sourcesallContacts: true, allChatContacts: false (illustrative)
Shows which categories of WhatsApp contacts you selected for export.
- Selected groups, labels, and broadcastsgroupContacts: [{name: "Sales Leads", id: "120363025001234567@g.us"}] (illustrative)
Can include the names and identifiers of WhatsApp groups, labels, or broadcast lists selected for export.
Captured request
The verification evidence records a POST to this endpoint containing userid and downloadData with contactCount.
- Content-Type
- application/json
The code that does this
The popup sends the contact-download selection to the WhatsApp tab
Readable contact-download payload builder
popup/contact.jsfunction o() { return { authid: authid, allContacts: s.allContactsEnabled, allChatContacts: s.allChatContactsEnabled, groupContacts: s.selectedGroups, labels: s.selectedLabels, broadcasts: s.selectedBroadcasts, isPro: isGoldorSilver() } }Readable contact-download click handler
popup/contact.js$("#downloadAllContacts").click(() => { s.showContactDownloadLimitLink = !isNinja(), t(), C(), sendMsgToActiveTab({ from: POPUP_JS, subject: MSG_LIB_DOWNLOAD_CONTACTS, data: o() })The code that does this
The content script posts contact-export metadata to Firebase
Readable spreadsheet export and metadata call
content/content.jsasync function downloadContactsFromLib(e) { let t; var n, o = { ...e, contactCount: 0 }, a = XLSX.utils.book_new(), r = new Set; if (e.allContacts && (n = await getSavedContactSheet(t = await contentLibhookInstance.getUserSavedContacts()), o.contactCount = t?.length, XLSX.utils.book_append_sheet(a, n, getValidSheetName(r, "Saved Contacts"))), e.allChatContacts && (n = await getWhatsAppContactSheet(t = await contentLibhookInstance.getUserWhatsAppContacts()), o.contactCount += t?.length, XLSX.utils.book_append_sheet(a, n, getValidSheetName(r, "Whatsapp Contacts"))), e.groupContacts) for (var s of e.groupContacts) { var c = await contentLibhookInstance.getUserGroupMemberContact(s.id), c = (o.contactCount += c?.length, await getMemberContactSheet(c)); let e = s.name; e = (e = e.replaceAll(/[\/\\\?\*\[\]]/gm, "-")).substring(0, 30), XLSX.utils.book_append_sheet(a, c, getValidSheetName(r, e)) } if (e.labels) for (var i of e.labels) { var l = await contentLibhookInstance.getLabelMembersMessage(i.name), E = await getMemberContactSheet(l); o.contactCount += l?.length, XLSX.utils.book_append_sheet(a, E, getValidSheetName(r, i.name)) } if (e.broadcasts) for (var _ of e.broadcasts) { var T = await contentLibhookInstance.getUserGroupMemberContact(_.id), C = await getMemberContactSheet(T); o.contactCount += T?.length, XLSX.utils.book_append_sheet(a, C, getValidSheetName(r, _.name)) } XLSX.writeFile(a, "Contacts.xls"), logContactDownloadDetail(e.authid, o)}Readable Firebase POST helper
content/content.jslet ROOT_URL = "https://us-central1-waplugin-34798.cloudfunctions.net", CONTACT_DOWNLOAD_DETAIL_URL = ROOT_URL + "/stats/contactdownload";async function logContactDownloadDetail(e, t) { try { await fetch(CONTACT_DOWNLOAD_DETAIL_URL, { method: "POST", mode: "cors", cache: "no-cache", credentials: "same-origin", headers: { "Content-Type": "application/json" }, redirect: "follow", referrer: "no-referrer", body: JSON.stringify({ userid: e, downloadData: t }) }) } catch (e) {}}External host receiving the contact-export metadata
- us-central1-waplugin-34798.cloudfunctions.net
Firebase Cloud Functions endpoint that receives the contact-download metadata POST.
WhatsApp Phone Number Cookie on wabiz.in
When the popup has a logged-in WhatsApp profile, it writes the phone number and display name into cookies scoped to wabiz.in.
This depends on a paired session; an earlier DA run hit the QR login wall and didn't exercise it.
What actually happens
You open the extension popup while WhatsApp is logged in.
The popup asks the active WhatsApp tab for the current profile before updating its view.
The extension writes your WhatsApp phone number and name into wabiz.in cookies.
The cookies are named eu and un and are set for a seven-day lifetime.
Cookie values written for wabiz.in
- WhatsApp phone cookieeu=+14155550132 (illustrative)
Lets wabiz.in receive the WhatsApp phone number associated with the extension session.
- WhatsApp display-name cookieun=Alex Chen (illustrative)
Adds the WhatsApp display name next to the phone number.
- Cookie lifetime604800 seconds (7 days)
Keeps those values available to wabiz.in after the popup writes them.
The code that does this
The popup reads the WhatsApp profile and writes wabiz.in cookies
Readable popup cookie writer
popup/popup.jsfunction updateView() { function e(t, n, a) { chrome.cookies.get({ url: a, name: t }, e => { e || chrome.cookies.set({ url: a, name: t, value: n, expirationDate: Date.now() / 1e3 + 604800 }) }) } var t; $("#wapluginVersion").html("WA Biz Sender - " + manifestData.version), loggedinUser && ($("#userDetails").html(`<span class="name">${loggedinUser.name}</span>` + '<span class="sep ml3 mr3">-</span>' + `<b>${loggedinUser.phoneNumber}</b>`), t = "https://wabiz.in/", e("eu", loggedinUser.phoneNumber, t), e("un", loggedinUser.name, t)), $("#mainMessageSendContainor").show(), isPageWebWhatsapp ? (activeTab === TAB_SHOWWHATSAPP_TAB && (activeTab = TAB_SEND_MSG), $("#" + TAB_SEND_MSG).show(), $("#" + TAB_PRO_ADD).show()) : (activeTab = TAB_SHOWWHATSAPP_TAB, $("#" + TAB_SEND_MSG).hide(), $("#" + TAB_PRO_ADD).hide()), $("#" + TAB_SHOWWHATSAPP_TAB).hide(), isPro && $("#" + TAB_PRO_ADD).hide(), (activeTab ? $("#" + activeTab) : $("#" + TAB_SEND_MSG)).tab("show"), isPro && alertControl.hideAllAlerts(), updateInfoBox(), updateSubscriptionFooter(), updateSendMessageView()}Readable profile lookup
popup/popup.jsasync function getUserInformation() { var e = await sendMsgToActiveTab({ from: POPUP_JS, subject: MSG_LIB_GET_LOGGEDIN_USER, data: "" }), e = (e && (loggedinUser = e, sendMsgToExtension({ from: CONTENT_JS, subject: MSG_SET_USER_PHONENUMBER, data: loggedinUser })), await sendMsgToActiveTab({ from: POPUP_JS, subject: MSG_LIB_GET_LOGGEDIN_USER, data: "" })); e?.phoneNumber && $("#whatsappDisconnectedWarning").addClass("d-none"), authPhoneNumber = e?.phoneNumber, authid = e?.phoneNumber, storageInstance.saveAuthId(e?.phoneNumber), updateView()}The code that does this
Manifest permissions allow the cookie write
"permissions": [ "storage", "cookies", "https://wabiz.in/", "alarms", "identity", "identity.email" ], "host_permissions": [ "https://wabiz.in/*" ],Cookie destination
- wabiz.in
Receives cookies scoped by the extension to https://wabiz.in/ when the browser later requests that site.
Where it sends data
Destinations our analysis observed WABiz Bulk Sender 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.
- us-central1-waplugin-34798.cloudfunctions.net
WABiz Bulk Sender sends data to us-central1-waplugin-34798.cloudfunctions.net. 8 other extensions we have analyzed send data here.
- wabiz.in
WABiz Bulk Sender sends data to wabiz.in. One other extension we have analyzed sends data here.