Is Helperbird: Accessibility & Productivity App safe?
Helperbird is medium risk. With popup Translate set to Helperbird's engine, the extension sends translated text (typed or from selection) to Helperbird's service with target/source language and formality. Runs after a subscription check and a click.
Who publishes itCoffee & Fun LLC - no other listings under this identity, 3 shared hostnames
Coffee & Fun LLC - no other listings under this identity, 3 shared hostnames
What this publisher told the store about itself, and the other listings that told it the same thing.
Shared hosts - 3 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
Popup translation sends selected or typed text to Helperbird
With popup Translate set to Helperbird's engine, the extension sends translated text (typed or from selection) to Helperbird's service with target/source language and formality.
Runs after a subscription check and a click.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-200
- Source
- Dynamic sandbox
You click Translate in the popup while the Helperbird engine is selected.
The code checks for a paid subscription before continuing on this path.
The extension sends the text to Helperbird's engine service for translation.
If the popup text box is empty, the extension first asks the active page for selected text.
- Text to translatePlease translate this paragraph for tomorrow's meeting.
This is the text you typed into the popup, or selected page text if the popup box was empty.
- Target languagees
This tells the service which language you want the text translated into.
- Source languageauto
This indicates the language the extension asks the service to translate from.
- Formality settingdefault
This adds a tone preference for the translation request.
The request helper expects a JSON response and raises an error for non-OK HTTP status codes.
- Content-Type
- application/json
Popup code that chooses Helperbird translation, gathers text, and posts the payload
Selected text source
scripts/popup.jsgetText() { return r5(this, null, function*() { const e = { message: "", error: !0 }, t = { app: "alert", popup: "selected", message: this.$helperbird_i18n("feature_analyze_singleText"), text: "", type: "success", engine: "front" }, r = yield vb(t); if (!0 === r.error) return e; const { text: n } = r; if ("string" == typeof n) return { message: n.trim(), error: !1 }; if ("object" == typeof n && (null == n ? void 0 : n.markdown)) { return { message: Dv(jk(n.markdown, { headerIds: !1, mangle: !1, breaks: !0, gfm: !0, silent: !0 })).trim(), error: !1 } } return "object" == typeof n && (null == n ? void 0 : n.textContent) ? { message: n.textContent.trim(), error: !1 } : e })}Helperbird translate path
scripts/popup.jsonTranslateClick() { "helperbird" !== this.engine ? this.googleTranslate() : this.translateText()},selectEngine(e) { "google" !== e && "helperbird" !== e || (this.engine = e, document.activeElement && "function" == typeof document.activeElement.blur && document.activeElement.blur())},translateText() { return r5(this, null, function*() { var e, t; if (!1 === this.paid) return yield this.delay(500), this.toaster({ message: this.$helperbird_i18n("alert_message_pro", "Helperbird"), type: "error" }), !1; this.isLoading = !0, this.convert = "", this.detectedSource = ""; let r, n = ""; if (this.inputText.trim().length > 0) n = this.inputText.trim(); else { const e = yield this.getText(); if (!0 === e.error || !e.message) return this.isLoading = !1, this.toaster({ message: this.$helperbird_i18n("you_need_to_highlight"), type: "info" }), !1; n = e.message } if (0 === n.trim().length) return this.isLoading = !1, this.toaster({ message: this.$helperbird_i18n("you_need_to_highlight"), type: "info" }), !1; try { r = yield function() { return Mb(this, arguments, function*(e = "", t = "en", r = "auto", n = {}) { let i = `${Lu.API_URL}api/v1/smart/translate`; return yield Ib(`${i}`, { fullText: e, targetLanguage: t, sourceLanguage: r, formality: n.formality || "default" }).then(e => e).catch(() => ({ accessDenied: !1, message: "Could not translate the text", data: {}, error: !0 })) }) }(n, this.targetLanguage, "auto") } catch (e) { r = { error: !0 } } return r && !0 !== r.error ? (this.convert = "string" == typeof(null == (e = null == r ? void 0 : r.data) ? void 0 : e.translated) ? r.data.translated : "", this.detectedSource = "string" == typeof(null == (t = null == r ? void 0 : r.data) ? void 0 : t.sourceLanguage) ? r.data.sourceLanguage : "", this.isLoading = !1, this.convert || this.toaster({ message: this.$helperbird_i18n("translate_text_error"), type: "error" }), !0) : (this.isLoading = !1, !0 === (null == r ? void 0 : r.accessDenied) ? this.toaster({ message: this.$helperbird_i18n("alert_message_pro", "Helperbird"), type: "error" }) : this.toaster({ message: this.$helperbird_i18n("translate_text_error"), type: "error" }), !1) })}POST helper
scripts/popup.jsfunction Ib() { return Eb(this, arguments, function*(e = "", t = {}, r = 3e4) { const n = new AbortController, i = setTimeout(() => n.abort(), r), o = JSON.stringify(t), s = Ab(e) ? yield yb("POST", Rb(e), o): {}; try { const t = yield fetch(e, { method: "POST", mode: "cors", cache: "no-cache", credentials: "same-origin", headers: Tb({ "Content-Type": "application/json" }, s), redirect: "follow", referrerPolicy: "no-referrer", body: o, signal: n.signal }); if (clearTimeout(i), !t.ok) throw new Error(`HTTP Error: ${t.status} ${t.statusText}`); try { return yield t.json() } catch (e) { throw new Error(`Failed to parse JSON response: ${e.message}`) } } catch (e) { if (clearTimeout(i), "AbortError" === e.name) throw new Error("Request timeout"); throw e } })}- engine.helperbird.app
Helperbird engine endpoint that receives the popup translation request.
What it can do
Permissions this extension asks for, as declared in version 2026.7.18. 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 2026.9.17, which we have not unpacked yet.
Read and change your data on every site you visit
http://*/* and 2 more
Read and change your data on every secure site you visit
https://*/*
Act on the current tab, but only after you click the extension
activeTab
Store data in your browser
storage
Add items to the right-click menu
contextMenus
Schedule its own background tasks
alarms
Show a panel beside the page
sidePanel
Run its own code inside the pages you visit
scripting