Is BeLikeNative – AI Paraphrasing Tool | Paraphrase, Rewrite & Translate Text safe?

Medium risk

BeLikeNative sends selected text from any website to its AI backend and transmits telemetry including visited domains to the same server.

When a user selects text and triggers a keyboard shortcut or toolbar button, the extension forwards that text to backend.belikenative.com with no domain restrictions — text selected on any page can be sent. The extension also runs a background telemetry system that batches and sends event data every 60 seconds, including the current page's domain, browser platform details, a persistent anonymous identifier, and user subscription and usage metrics.

Autom8 LLCv1.8.17Chrome Web Store
45Risk
Who publishes it

Autom8 LLC - 13 other listings 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
Autom8 LLC

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.

backend.belikenative.com
Also called by 1 other listing: BeLikeNative

AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.

Publishers can request a review.

Findings

Telemetry sends page context and usage metrics to BeLikeNative

MediumunwantedCWE-359Dynamic sandbox

We observed a POST to backend.belikenative.com carrying telemetry: session, ext/browser version, platform, locale, analytics ID, plan, fix count.

What actually happens

You did this

You browse websites while BeLikeNative is installed.

The manifest runs the content script on every URL pattern.

The extension did this

The extension queues telemetry that can include page domain context and usage metrics.

Queued events are sent to the BeLikeNative backend in JSON batches.

Captured request

POSThttps://backend.belikenative.com/telemetry/events

Telemetry fields sent or prepared by the extension

  • Session identifier
    6f2b1bb0-5a74-4e3c-b9ab-4f692f80f5c1 (illustrative)

    Lets separate events from the same browser session be grouped together.

  • Extension and browser versions
    extension 1.8.5; Chrome 148.0.0.0

    Shows which extension build and Chrome version produced the telemetry.

  • Platform and language
    Linux x86_64; en-US

    Adds device and locale context to the event stream.

  • Current page domain
    docs.example.com (illustrative)

    Can show which website was open when an extension error or message failure happened.

  • Analytics identifier
    0000000000000000

    Lets analytics events stay linked across browsing sessions after installation.

  • Plan and fix metrics
    plan free; fixes 0

    Shows account tier and usage counters such as the number of corrections made.

When this fires

Every 1 minute · flushes at 50 queued events

Telemetry is uploaded every minute, and the queue can flush sooner after 10 events are waiting.

The code that does this

Telemetry construction, batching, persistent analytics ID, and page-domain context

Readable version

Builds a telemetry event with browser, platform, locale, timestamp, and context fields

js/background.js
function b(e, t, r) {  if (!e) throw new Error("type required");  const n = function() {      if (i) return i;      let e = "unknown";      try {        e = chrome.runtime.getManifest().version || e      } catch {}      return i = {        v: e,        c: h(navigator.userAgent),        p: navigator.platform || "unknown",        l: navigator.language || "unknown"      }, i    }(),    o = {      sessionId: s || "pending",      extensionVersion: n.v,      chromeVersion: n.c,      platform: n.p,      locale: n.l,      type: e,      timestamp: (new Date).toISOString(),      context: {        ...t,        entryPoint: t.entryPoint || a      }    };  var c;  return r instanceof Error && (o.error = {    name: r.name || "Error",    message: (r.message || "").slice(0, 500),    stack: r.stack ? (c = r.stack, c && "string" == typeof c ? c.replace(g, "[JWT]").replace(p, "[EMAIL]").replace(y, "").replace(_, "").slice(0, 2e3) : "") : void 0  }), o}

Queues events and flushes when 10 are waiting

js/background.js
function w(e) {  e && "string" == typeof e.type && (o >= 100 || (n = [...n, e], o += 1, n.length >= 10 && k()))}

Posts up to 50 queued events to the telemetry endpoint

js/background.js
async function k() {  if (0 === n.length) return;  if (!await async function() {      return new Promise(e => {        try {          chrome.storage.local.get([r], t => {            chrome.runtime.lastError ? e(!0) : e(!1 !== t[r])          })        } catch {          e(!0)        }      })    }()) return void(n = []);  const t = await f(),    o = n.slice(0, 50);  n = n.slice(o.length), await async function(t) {    if (!t || 0 === t.length) return;    const r = l ? `${e}?dry_run=true` : e,      n = new AbortController,      o = setTimeout(() => n.abort(new DOMException("Request timed out", "TimeoutError")), 5e3);    try {      const e = await fetch(r, {        method: "POST",        headers: {          "Content-Type": "application/json"        },        body: JSON.stringify({          events: t.slice(0, 50)        }),        signal: n.signal      });      l && await async function(e, t) {        try {          const r = await t.json();          ! function(e) {            if (0 === e.rejected) console.log("%c[BLN Dry Run] ALL ACCEPTED (%d/%d)", "color: #00b894; font-weight: bold;", e.accepted, e.total);            else {              console.warn("%c[BLN Dry Run] REJECTED %d/%d", "color: #d63031; font-weight: bold;", e.rejected, e.total);              for (const t of e.errors) console.warn("  [%d] %s: %s", t.index, t.field, t.error)            }          }(r);          const n = v(e, r);          u.push(n), u.length > 50 && (u = u.slice(-50)), await async function() {            const e = m();            if (e) try {              e.set({                [d]: u              })            } catch {              u = u.slice(-10);              try {                e.set({                  [d]: u                })              } catch {}            }          }()        } catch (t) {          const r = t instanceof Error ? t.message : "unknown";          u.push(v(e, {            error: `Response parse failed: ${r}`          }))        }      }(t, e)    } catch (e) {      if (l) {        const t = e instanceof Error ? e.message : "unknown";        console.error("%c[BLN Dry Run] NETWORK ERROR: %s", "color: #d63031; font-weight: bold; font-size: 13px;", t)      }    } finally {      clearTimeout(o)    }  }(o.map(e => "pending" === e.sessionId ? {    ...e,    sessionId: t  } : e))}

Adds analytics data with persistent identifier and user metrics

js/background.js
function U(e, t) {  try {    if (!e || "string" != typeof e || !A.has(e) || !N) return;    q += 1;    const r = (new Date).toISOString();    let n = "unknown";    try {      n = chrome.runtime.getManifest().version || n    } catch {}    w({      sessionId: "analytics",      extensionVersion: n,      chromeVersion: "n/a",      platform: M.platform,      locale: M.lang,      type: "analytics",      timestamp: r,      context: {        entryPoint: "background"      },      analyticsData: {        type: "analytics",        anon_id: L || "0000000000000000",        event: e,        props: t && "object" == typeof t ? {          ...t        } : {},        user: {          ...M        },        seq: q,        ts: r      }    })  } catch {}}

Creates or loads the persistent 16-character analytics identifier

js/background.js
async function(e) {  if (e && !N) try {    N = !0, await async function() {      if (L) return L;      const e = (await O([I]))[I];      if ("string" == typeof e && 16 === e.length) return L = e, L;      let t = "unknown";      try {        t = chrome.runtime.id || t      } catch {}      const r = await O([D]);      let n = "string" == typeof r[D] && r[D] ? r[D] : "";      n || (n = String(Date.now()), await j({        [D]: n      }));      const o = new Uint8Array(await crypto.subtle.digest("SHA-256", (new TextEncoder).encode(t + "_" + n)));      let a = "";      for (let e = 0; e < o.length && a.length < 16; e++) a += o[e].toString(16).padStart(2, "0");      return L = a.slice(0, 16), await j({        [I]: L      }), L    }();    const t = await O([P]);    t[P] && "object" == typeof t[P] && (M = C(R, t[P])), x(e)  } catch {}}("background")

Adds the current page domain to content-script error telemetry

js/content_script.js
window.addEventListener("error", e => {  try {    e.filename && e.filename.includes(chrome.runtime.id) && _(e.error || new Error(e.message), {      domain: location.hostname    })  } catch (e) {}})

Where it sends data

Destinations our analysis observed BeLikeNative – AI Paraphrasing Tool | Paraphrase, Rewrite & Translate Text 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.

  • backend.belikenative.com

    BeLikeNative – AI Paraphrasing Tool | Paraphrase, Rewrite & Translate Text sends data to backend.belikenative.com. No other extension we have analyzed sends data here.

Updated 2 November 2026gchojmpfpbpmpfgdppfdkpchikbcgabp