Is Api4Com - Extensão para Navegadores safe?

High risk

Api4Com is high risk. Starting a call from the extension dialer makes the popup prepare the contact, add the SIP username and Api4Com access token, and post the call payload to Api4Com, including the target phone number and any CRM metadata on the contact.…

adminv4.35.0Chrome Web Store
75Risk
Who publishes it

API4COM TECNOLOGIA E SERVICOS LTDA - 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
admin
Declared legal entity
API4COM TECNOLOGIA E SERVICOS LTDA
Registered address
ROD SC 401, 4150, Florianópolis, SC 88032005, BR
Registered contact
Api4Com

Same store account

1 other listing published from this account, 7k+ 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.

app.moskitcrm.com
Also called by 2 other listings, including Ollow Web (Moskit Boost)
app.nectarcrm.com.br
Also called by 3 other listings, including Nectar for Whats

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

Call initiation posts phone and CRM metadata to Api4Com

Starting a call from the extension dialer makes the popup prepare the contact, add the SIP username and Api4Com access token, and post the call payload to Api4Com, including the target phone number and any CRM metadata on the contact.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You start a call from the Api4Com popup or an injected dialer contact.

The extension did this

The extension posts the target phone number, SIP extension username, access token, and contact metadata to Api4Com.

02EvidenceNETWORK CAPTURE
Captured request
POSThttps://api.api4com.com/api/v1/dialer
Code resolves the Api4Com /dialer response data on success and handles 401, 402, 403, 422, and 503 error cases.
Headers
AuthorizationBearer <redacted>
03EvidenceFIELD TABLE
Fields assembled for the dialer POST
FieldValueWhy it matters
Target phone number
+55 11 91234-5678 (illustrative)Identifies the number the extension asks Api4Com to call.
SIP extension username
sip-user-123 (illustrative)Links the call request to the configured phone extension account.
Api4Com access token
eyJhbGciOiJIUzI1NiJ9.redactedAuthorizes the extension session used for the dialer API call.
CRM gateway
hubspotShows which CRM integration produced the selected contact.
Contact URL
https://app.hubspot.com/contacts/123/contact/456/view (illustrative)Keeps the CRM page associated with the outgoing call request.
CRM entity IDs
{"contact":"456"} (illustrative)Carries CRM-specific identifiers such as contact, deal, company, ticket, or lead IDs.
04EvidenceCODE COMPARE
The code that does this

Contact preparation and /dialer POST

What it actually does
Readable contact preparation adds the extension username and access tokendeobfuscated/popup.js
prepareContact(t) {
          if (!this.extension) return !1;
          if (!this.extension.username) return !1;
          const e = {
            ...t
          };
          return e.data || (e.data = {}), e.data.extension = this.extension.username, e.metadata || (e.metadata = {}), this.token && this.token.id && (e.metadata.api4comAccessToken = this.token.id), e
        },
Readable call sender builds the phone, extension, and metadata objectdeobfuscated/popup.js
sendCallToAPI({
          data: {
            phone: t,
            extension: e
          },
          metadata: n
        }) {
          const r = {
            phone: t,
            extension: e,
            metadata: n
          };
          return this.$store.dispatch("integrationCall", r).then(r => (this.isDebug && console.info("Api4Com > ContactDialer > sendCallToAPI >", t, e, n, r), r)).catch(t => {
            this.isDebug && console.error("Api4Com > ContactDialer > sendCallToAPI >", t.message), 422 === t.statusCode && "InvalidPhoneNumber" === t.name && this.toast.error(chrome.i18n.getMessage("webphoneClickToCallInvalidNumber")), 401 === t.statusCode && (this.toast.error(chrome.i18n.getMessage("mainErrorExpiredToken")), setTimeout(() => {
              document.location.reload()
            }, 1e4)), 402 === t.statusCode && this.toast.error(chrome.i18n.getMessage("webphoneCallBlockedNoMinutes")), 403 === t.statusCode && "CallBlockedByUserStatus" === t.name && this.toast.error(chrome.i18n.getMessage("webphoneCallBlockedUserNotActive")), 503 === t.statusCode && this.toast.error(chrome.i18n.getMessage("webphoneCallTemporarilyUnavailable"))
          })
        },
Readable store action posts to /dialer with the configured tokendeobfuscated/popup.js
function Qm({
      commit: t,
      state: e
    }, n) {
      return Fm.configToken(e.token.id), Fm.post("/dialer", n).then(({
        data: t
      }) => Promise.resolve(t)).catch(e => (401 === e.statusCode && zm(t), Promise.reject(e)))
    }
05EvidenceTHIRD PARTY LIST
Remote host receiving call requests
  • api.api4com.com

    Api4Com API host receiving /dialer requests containing the call target, SIP extension username, token metadata, and CRM context.

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-200
SourceAI SANDBOX

Clipboard Text Read During Webphone Paste

Pasting into the webphone dialer makes the handler read clipboard text, strip it to dialable characters, and feed them to the dialpad.

The extension requests clipboard-read; testing saw no outbound transmission of clipboard contents.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You paste text into the extension's webphone dialer.

The listener is attached when the webphone component mounts.

The extension did this

The extension reads the current clipboard text and uses the dialable characters as dialpad input.

Dynamic analysis confirmed the paste listener and did not observe clipboard contents being sent over the network.

02EvidenceFIELD TABLE
Clipboard values handled by the paste flow
FieldValueWhy it matters
Current clipboard text
Client Ana +55 (11) 91234-5678 ext #42 (illustrative)Clipboard text is read on paste in the dialer. That can include more context than the phone number ultimately dialed.
Dialable characters
+5511912345678#42 (illustrative)After reading the clipboard, the extension keeps numbers and phone-control characters for dialing.
Clipboard-read permission
clipboardReadThe installed extension is granted permission to read clipboard text in its own extension pages.
03EvidenceCODE COMPARE
The code that does this

Paste listener and clipboard read in the shipped popup bundle

What it actually does
The helper keeps only dialpad characters after the clipboard readdeobfuscated/popup.js
function dO(t) {
  return t.replaceAll(/[^0-9+*#]/g, "")
}
The webphone component registers the paste listener when mounteddeobfuscated/popup.js
mounted() {
  this.$nextTick(() => {
    this.extension && !0 !== this.extension.external && (this.checkMicrophonePermission().then(() => {
      this.initialize().then(() => {
        this.startDebug(), this.userAgentStatus(), this.applyVolumes(), this.emitter.emit("refresh-media-devices"), dispatchEvent(new Event("load"))
      })
    }), this.addListenerToPaste())
  })
}
The paste handler reads clipboard text, filters it, and dials each characterdeobfuscated/popup.js
async pasteEventListener() {
  navigator.clipboard.readText().then(t => {
    const e = dO(t);
    this.isDebug && console.info("Api4Com > Webphone > clipboard paste >", e), this.webphone && this.webphone.getDialpad() && e.split("").forEach(t => {
      this.webphone.getDialpad().dial(t, !1)
    })
  }).catch(t => {
    this.isDebug && console.info("Api4Com > Webphone > error clipboard paste >", t.message), this.toast.error(gO)
  })
}
addListenerToPaste() {
  document.addEventListener("paste", this.pasteEventListener)
}
removeListenerToPaste() {
  document.removeEventListener("paste", this.pasteEventListener, !1)
}
Updated 30 September 2026nmihkcakhpccmdhoifppbgeoapjaanno