Is Immersive Reader - Improve Reading Accessibility safe?
Immersive Reader - Improve Reading Accessibility sends login details and selected page text to Amplitude analytics.
When users submit the extension's account login flow, the extension forwards the login request object, including email and verification code fields, through Amplitude telemetry. When users choose its read-selection context menu item, it also sends the selected page text and page URL in an Amplitude event.
Who publishes itMark - 5 other listings from the same operator, 2 of them carrying a finding
Mark - 5 other listings from the same operator, 2 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
5 other listings published from this account, 207k+ users between them. 2 of them carry a finding.
Shared hosts - 1 hostname
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
Login codes are passed into Amplitude analytics
Submitting the account login form sends your email and code to the background worker, which logs the full runtime request in an Amplitude event 'Bg Runtime Msg' before handling it; the client posts to api2.amplitude.com/2/httpapi.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-522
- Source
- Dynamic sandbox
You submit the extension account login form.
The form requires an email address and the verification code sent for that account.
The background service worker passes the full login request into an Amplitude analytics event.
The request object contains the account command, login subcommand, email address, and verification code.
- Email addressemployee@example.com (illustrative)
Identifies the account you are trying to sign in to through the extension.
- Verification code482913 (illustrative)
Represents the one-time code you typed during the account login flow.
- Login commandaccount / login
Shows that the message belongs to the account login flow, not a general page event.
- Extension contextImmersive Translate, version 2.2.0
Adds extension name and version context around the account request.
Amplitude HTTP API endpoint configured by the bundled client; no request body was recorded in the available evidence.
The login form payload is logged before the account handler runs
Login click handler from home.js
home.jsR = function() { var e = bt(xt().mark((function e() { return xt().wrap((function(e) { for (;;) switch (e.prev = e.next) { case 0: gr.debug("in PanelAccount handleClickLogin"), e.prev = 1; case 2: if (E(!0), b) { e.next = 6; break } return alert("Please input login code"), e.abrupt("break", 9); case 6: return e.next = 8, chrome.runtime.sendMessage({ cmd: "account", payload: { cmd: "login", payload: { email: v, verifycode: b } } }).then((function(e) { var t; if (gr.debug("sendMsg[account:login] rsp:", e), 0 !== e.errcode) alert(e.errmsg || "login error"); else if (0 !== (null === (t = e.rslt) || void 0 === t ? void 0 : t.errcode)) { var n; alert((null === (n = e.rslt) || void 0 === n ? void 0 : n.errmsg) || "login error") } else h(0) })); case 8: case 9: e.next = 15; break; case 11: e.prev = 11, e.t0 = e.catch(1), gr.debug("handleClickLogin catch err:", e.t0.message), alert(e.t0.message); case 15: return e.prev = 15, E(!1), e.finish(15); case 18: case "end": return e.stop() } }), e, null, [ [1, 11, 15, 18] ]) }))); return function() { return e.apply(this, arguments) }}()Background runtime-message listener from background.js
background.jschrome.runtime.onMessage.addListener((function(e, t, n) { if (b.debug("in handleRuntimeOnMessage, req:", e), b.debug("in handleRuntimeOnMessage, sender:", t), yn("Bg Runtime Msg", { extname: p.ext.name, status: "begin", cmd: e.cmd, req: e }), "access" === e.cmd) return wn(e, t, n), !0; if ("read_selection" === e.cmd) { var r = function() { var t = a(l().mark((function t() { var r, i, o, u; return l().wrap((function(t) { for (;;) switch (t.prev = t.next) { case 0: return r = null, t.prev = 1, t.next = 4, chrome.tabs.query({ active: !0, currentWindow: !0 }); case 4: return i = t.sent, o = s(i, 1), u = o[0], b.debug("current tab:", u), t.next = 10, chrome.scripting.executeScript({ target: { tabId: u.id }, files: ["content.js"] }); case 10: r = { errcode: 0, errmsg: "processing..." }, t.next = 17; break; case 13: t.prev = 13, t.t0 = t.catch(1), b.error("catch err:" + t.t0.message), r = { errcode: -1, errmsg: "catch err:" + t.t0.message }; case 17: b.debug("sendrsp:", JSON.stringify(r)), n(r), yn("Bg Runtime Msg", { extname: p.ext.name, status: "end", cmd: e.cmd, rsp: r }); case 20: case "end": return t.stop() } }), t, null, [ [1, 13] ]) }))); return function() { return t.apply(this, arguments) } }(); return r(), !0 } if ("account" === e.cmd) return In(e, t, n), !0; if ("open_page" === e.cmd) { chrome.tabs.create({ url: e.payload.url }); var i = { errcode: 0, errmsg: "success" }; b.debug("sendrsp:", JSON.stringify(i)), n(i), yn("Bg Runtime Msg", { extname: p.ext.name, status: "end", cmd: e.cmd, rsp: i }) } else { var o = { errcode: -1, errmsg: "wrong req.msg" }; b.debug("sendrsp:", JSON.stringify(o)), n(o), yn("Bg Runtime Msg", { extname: p.ext.name, status: "end", cmd: e.cmd, rsp: o }) }}))Amplitude setup from background.js
background.jst = { name: "production", backend: "https://api.immersivereader.org/api", web: "", amp_key: "9ab9d6d011bd7a8b870db400e2545d28"}, e.exports = { env: t}var G = "AMP", Y = "".concat(G, "_unsent"), Z = "https://api2.amplitude.com/2/httpapi"yn = Gt.trackb.debug("background.js run, date: ", Date()), a(l().mark((function e() { return l().wrap((function(e) { for (;;) switch (e.prev = e.next) { case 0: return e.t0 = t, e.t1 = p.amp.key, e.t2 = void 0, e.next = 5, U(); case 5: e.t3 = e.sent, e.t4 = { defaultTracking: !1, deviceId: e.t3 }, e.t0.init.call(e.t0, e.t1, e.t2, e.t4); case 8: case "end": return e.stop() } }), e)})))();- api2.amplitude.com
Amplitude HTTP analytics endpoint that receives events from the bundled Amplitude client.
- api.immersivereader.org
Extension backend used for account API calls; the same login request is separately passed into the analytics event before this account handler runs.
Selected text and page URLs sent to Amplitude from context-menu clicks
When you use the extension's selection context menu, it forwards the click data to Amplitude at api2.amplitude.com/2/httpapi, including selected page text and page URL, and sometimes related link, image, or frame URLs.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-359
- Source
- Dynamic sandbox
User selects text and clicks the extension's context-menu item.
The extension sends the context-menu click data, including selected text and page URL, to Amplitude analytics.
- Selected page textSelected paragraph text (illustrative)
Text selected on the page is included in the analytics event, which can reveal page content the user highlighted.
- Page URLhttps://example.com/article (illustrative)
The source page address is included with the context-menu event, linking the selection to a specific page.
What it can do
Permissions this extension asks for, as declared in version 2.2.0. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.
Read and change your data on immersivereader.org
https://*.immersivereader.org/
Store data in your browser
storage
Add items to the right-click menu
contextMenus
Act on the current tab, but only after you click the extension
activeTab
Run its own code inside the pages you visit
scripting
Where it sends data
Destinations our analysis observed Immersive Reader - Improve Reading Accessibility 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.
- api2.amplitude.comwidely used
Immersive Reader - Improve Reading Accessibility sends data to api2.amplitude.com. A widely used service: 41 other extensions we have analysed send data here.