Is Google Meet Translation and AI Note Taker safe?
JotMe is high risk. We observed the extension send popup metrics to api.jotme.io when the popup opened. The request included the active tab URL and a list of other open tab URLs, including pages outside Google Meet such as chrome://extensions/ and about:blank.
Who publishes itJotme Limited - 3 other listings from the same operator, 3 of them carrying a finding
Jotme Limited - 3 other listings from the same operator, 3 of them carrying a finding
What this publisher told the store about itself, and the other listings that told it the same thing.
Same store account
3 other listings published from this account, 1k+ users between them. 3 of them carry a finding.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Open tab URLs sent to JotMe when the popup opens
We observed the extension send popup metrics to api.jotme.io when the popup opened.
The request included the active tab URL and a list of other open tab URLs, including pages outside Google Meet such as chrome://extensions/ and about:blank.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-200
- Source
- Dynamic sandbox
You open the extension popup or start a new chat from the popup.
The extension sends a metrics event containing the active tab URL and other open tab URLs to JotMe.
Dynamic analysis captured two outbound POST requests; the server returned 400 because the bearer token was not accepted.
- Authorization
- Bearer <redacted>
- Active tab URLhttps://app.jotme.io/
Shows the page you had active when the popup event was created.
- Other open tabschrome://extensions/
Shows additional pages open in the browser at the same time, even when they are not Google Meet pages.
- Another open tababout:blank
Adds more browsing context from the same browser session.
- Popup event typeOpen
Shows whether the event came from opening the popup, closing it, or starting a new chat.
- Extension access tokenBearer <redacted>
Ties the metrics request to the signed-in extension session.
Popup metrics message and service-worker tab enumeration
Popup helper sends popupMetrics messages
popup/assets/index-CNQREzUr.jsclass Rm {}Cr(Rm, "send", o => { const c = WO.safeParse(o); if (!c.success) return; const d = { message: "popupMetrics", ...c.data }; chrome.runtime.sendMessage(d)});Popup Open and NewChat call sites
popup/assets/index-CNQREzUr.js C(""), ye(!1), Ht(l[d].translate.languageDetection.placeholder), fe(!1), Ue(""), ft(""); const Ne = jS(); Xt(Ne), (Ye = At.current) == null || Ye.focus(), Rm.send({ chatSessionId: Ne, type: "NewChat" }) Xt(oe), C(be.popup.chatInput ?? ""), Kt(Z), F(((vt = be.popup.explain) == null ? void 0 : vt.chats) ?? []), y(((Dt = be.popup.translate) == null ? void 0 : Dt.targetLanguage) ?? "en"), console.log("popup chats ", (Ge = be.popup.translate) == null ? void 0 : Ge.chats), B(((rt = be.popup.translate) == null ? void 0 : rt.chats) ?? []), Ue(((It = be.popup.translate) == null ? void 0 : It.translateSource) ?? ""), ft(((Rn = be.popup.translate) == null ? void 0 : Rn.translateContext) ?? ""), Ht(((ua = be.popup.translate) == null ? void 0 : ua.sourceLanguage) ?? ""), Rm.send({ chatSessionId: oe, type: "Open" })Service worker handles popupMetrics and posts the request
service-worker.js s = e => { const { message: o } = e, t = r(e, ["message"]); n(void 0, void 0, void 0, (function*() { var e; if ("popupMetrics" !== o) return; const n = yield chrome.tabs.query({ active: !0, currentWindow: !0 }), r = (yield chrome.tabs.query({})).filter((e => { var o; return (null == e ? void 0 : e.id) !== (null === (o = null == n ? void 0 : n[0]) || void 0 === o ? void 0 : o.id) })); if ("Close" !== t.type) { const o = { activeTabHref: null === (e = null == n ? void 0 : n[0]) || void 0 === e ? void 0 : e.url, otherTabs: r.map((e => null == e ? void 0 : e.url)).filter((e => void 0 !== e)).map((e => ({ href: e }))) }; t.activeTabURL = o.activeTabHref, t.otherTabs = o.otherTabs } const i = (yield chrome.storage.local.get("access")).access; if ("" === t.chatSessionId) { const e = yield chrome.storage.local.get("popup"); t.chatSessionId = e.popup.sessionId } fetch("https://api.jotme.io/jotme/popup/metrics", { method: "POST", body: JSON.stringify(t), headers: { Authorization: `Bearer ${i}` } }) })) },- api.jotme.io
Receives popup metrics events containing the active tab URL and other open tab URLs.