Is 셀러라이프 safe?

High risk

셀러라이프 is high risk. When you select text on a page or in a field and click translate, the extension sends it to sellerlife.co.kr with a persistent UUID header and an encrypted header repeating the UUID, extension ID, and first ten characters of the text.

SELLERLIFEv1.2.1.90Chrome Web Store
72Risk
Who publishes it

주식회사 - no other listings under this identity, 4 shared hostnames

What this publisher told the store about itself, and the other listings that told it the same thing.

Publisher
SELLERLIFE
Declared legal entity
주식회사
Registered address
시흥대로193, 402호, 금천구, 서울특별시 08635, KR
Registered contact
셀러라이프

Shared hosts - 4 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.

sellerpick.co.kr
Also called by 1 other listing: 셀러픽
sellochomes.co.kr
Also called by 1 other listing: Chibiz 소싱·마진 어시스턴트
lotteglogis.com
Also called by 3 other listings, including 셀러픽
login.coupang.com
Also called by 6 other listings

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

Publishers can request a review.

Findings

Selected text sent to sellerlife.co.kr with persistent ID

When you select text on a page or in a field and click translate, the extension sends it to sellerlife.co.kr with a persistent UUID header and an encrypted header repeating the UUID, extension ID, and first ten characters of the text.

Severity
High unwanted
Type
Unexpected
CWE
CWE-359
Source
Dynamic sandbox
What actually happens
You did this

You select text on a webpage or inside a text field and click the translation control.

The control is injected on every matched page by the extension content script.

The extension did this

The extension sends that selected text to sellerlife.co.kr with a persistent extension UUID.

The request also carries an encrypted header containing the extension ID, UUID, and the first ten characters of the selected text.

Fields the translation request builds in code
  • Selected text
    wireless keyboard replacement policy

    The words you highlighted are sent for translation. If you highlight sensitive page or form text, that selected text is included.

  • Source language
    ko

    The request can include the language the extension is translating from.

  • Target language
    en

    The request can include the language the extension is translating into.

  • Persistent extension ID
    9b24c2b1-49ad-46cf-86c0-b8a0df8f82c4

    A UUID kept by the extension can link separate translation requests from the same browser install.

  • Encrypted request header
    {"eid":"cgococegfcmmfcjggpgelfbjkkncclkf","uuid":"9b24c2b1-49ad-46cf-86c0-b8a0df8f82c4","so":"wireless k"}

    The encrypted header repeats the persistent ID and includes the first part of the selected text.

Captured request
POSThttps://sellerlife.co.kr/pc/chrome-extension

The static proof path expects a JSON response consumed by then(e => e.json()). Observed traffic did not include this POST; only extension-domain GETs to sellochomes.co.kr were observed when the translation click path was not exercised.

The code that does this

Content-script selection capture and iframe handoff

Readable version

Manifest injects the translation content script on all URLs

manifest.json
{      "js": ["translate/translate.js"],      "matches": ["<all_urls>"],      "run_at": "document_end",      "all_frames": true    }

Clicking the translation control posts the selected text to the iframe

translate/translate.js
if (!!n.target.closest(".sellerlife-translate-btn") || !!n.target.closest(".sellerlife-translate-btn-text") || "s-translate-icon" === n.target?.id) {        n.preventDefault(), n.stopPropagation(), d.style.display = "none", a.classList.remove("menu-open");        const e = r.getAttribute("text");        if (!e) return;        await k();        const t = 12,          o = 650,          i = 414,          c = a.getBoundingClientRect(),          u = {            left: c.left + window.scrollX + T(),            top: c.top + window.scrollY + R()          },          p = w || {            left: u.left,            top: u.top,            right: u.left + 35,            bottom: u.top + 35          },          m = (document.documentElement.clientWidth || window.innerWidth) + window.scrollX + T(),          f = (document.documentElement.clientHeight || window.innerHeight) + window.scrollY + R();        let y = p.right + 10,          g = p.top;        y + o + t > m && (y = p.left - o - 10, y < window.scrollX + T() + t && (y = window.scrollX + T() + t)), g + i + t > f && (g = f - i - t), g < window.scrollY + R() + t && (g = window.scrollY + R() + t), s.style.left = `${y}px`, s.style.top = `${g}px`, s.style.display = "block", l = !0, N(), await async function(e) {          await k(), s?.contentWindow && s.contentWindow.postMessage({            type: "s-translate-select-open",            text: e          }, "*")        }(e)      }    })))  }

Mouseup handler reads input-field selections and page selections

translate/translate.js
function Y(e) {    if (!n) return;    if (m && !f && !d(e.target)) return P(), H(), B(), A(), w = null, y = null, $(), m = !1, void(f = !1);    const t = 12,      o = window.scrollX,      i = window.scrollY,      s = document.documentElement.clientWidth || window.innerWidth,      a = document.documentElement.clientHeight || window.innerHeight;    L = o, x = i;    const c = document.activeElement;    if (c && ("INPUT" === c.tagName || "TEXTAREA" === c.tagName)) {      const n = function(e) {        if (!e || !("selectionStart" in e) || !("selectionEnd" in e)) return "";        const {          selectionStart: t,          selectionEnd: n,          value: o        } = e;        return null == t || null == n || t === n ? "" : (o || "").substring(t, n)      }(c).trim();      if (!n) return d(e.target) || (P(), H(), B(), A()), w = null, y = null, $(), m = !1, void(f = !1);      l = !1, V();      const u = I(c),        C = {          left: u.left - o - T(),          top: u.top - i - R(),          right: u.right - o - T(),          bottom: u.bottom - i - R()        },        L = r.offsetWidth || 25,        x = r.offsetHeight || 25,        S = _(c);      let W, N;      if (g = S ? "fixed" : "doc", "fixed" === g) r.style.position = "fixed", W = C.right + 8, N = C.bottom + 8, W + L + t > s && (W = C.left - 8 - L), N + x + t > a && (N = a - x - t), W < t && (W = t), N < t && (N = t);      else {        r.style.position = "absolute", W = u.right + 8, N = u.bottom + 8;        const e = s + o + T(),          n = a + i + R();        W + L + t > e && (W = u.left - 8 - L), N + x + t > n && (N = n - x - t), W < o + T() + t && (W = o + T() + t), N < i + R() + t && (N = i + R() + t)      }      return r.style.left = `${W}px`, r.style.top = `${N}px`, r.style.display = "block", p(), r.setAttribute("text", n), w = {        ...u      }, y = "input", v = null, h = null, b = c, E = c.selectionEnd ?? null, M(c), l = !1, k(), V(), m = !1, void(f = !1)    }    const u = window.getSelection();    if (!u || u.isCollapsed || !u.rangeCount) return d(e.target) || (P(), H(), B(), A()), w = null, y = null, $(), m = !1, void(f = !1);    const C = u.toString().trim();    if (!C) return P(), H(), B(), A(), w = null, y = null, $(), m = !1, void(f = !1);    l = !1, k(), V();    const S = u.getRangeAt(0),      W = S.getClientRects?.(),      N = W && W.length ? W[W.length - 1] : (() => {        const e = S.cloneRange();        return e.collapse(!1), e.getBoundingClientRect()      })(),      X = {        left: N.left + o + T(),        top: N.top + i + R(),        right: N.right + o + T(),        bottom: N.bottom + i + R()      },      z = r.offsetWidth || 25,      D = r.offsetHeight || 25,      Y = 1 === S.endContainer.nodeType ? S.endContainer : S.endContainer.parentElement,      O = _(Y);    let U, F;    if (g = O ? "fixed" : "doc", "fixed" === g) r.style.position = "fixed", U = N.right + 8, F = N.bottom + 8, U + z + t > s && (U = N.left - 8 - z), F + D + t > a && (F = a - D - t), U < t && (U = t), F < t && (F = t);    else {      r.style.position = "absolute";      const e = s + o + T(),        n = a + i + R();      U = X.right + 8, F = X.bottom + 8, U + z + t > e && (U = X.left - 8 - z), F + D + t > n && (F = n - D - t), U < o + T() + t && (U = o + T() + t), F < i + R() + t && (F = i + R() + t)    }    r.style.left = `${U}px`, r.style.top = `${F}px`, r.style.display = "block", p(), r.setAttribute("text", C), w = {      ...X    }, y = "content", v = S.cloneRange(), h = Y, b = null, E = null, M(Y), m = !1, f = !1  }
The code that does this

Translation iframe builds the sellerlife.co.kr POST

Readable version

Request builder and POST

translate/translate-sl.js
async function a(e, t = void 0, o = void 0) {  if (null == (e = e.trim()) || "" == e) return;  if (r.source == t && r.target == o && r.text == e) return r;  let c;  c = null == t || null == o ? {    text: e  } : {    text: e,    source: t,    target: o  };  let a = {      eid: chrome.runtime.id,      uuid: n(),      so: e.slice(0, 10)    },    s = new JSEncrypt;  s.setKey(function(e) {    for (var t = [], r = 0; r < e.length; r += 2) t.push(parseInt(e.substr(r, 2), 16));    return decodeURIComponent(escape(String.fromCharCode.apply(null, t)))  }("2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0d0a4d4947664d413047435371475349623344514542415155414134474e4144434269514b426751436c6b6d336931694a6b53596e68546f656f6535312b674e4c670d0a686a412f47364d32767570372b6764392f6d566f4f347a4c6f2f313179794d68736678416e62514a37582f64616e704667375159614943487a786c41576259410d0a79356233674d2b35784641464b5241623859646b2b305a38367a463147515774543363383934345157663469584e2f63566857317932584a38466d3151614a6c0d0a3351364f4f7a36336c4d635368786f3936514944415141420d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d"));  let l = s.encrypt(JSON.stringify(a));  return fetch("https://sellerlife.co.kr/pc/chrome-extension", {    method: "POST",    mode: "cors",    cache: "no-cache",    credentials: "include",    headers: {      "Content-Type": "application/json",      uuid: n(),      et: l    },    referrerPolicy: "no-referrer",    body: JSON.stringify(c)  }).then((e => e.json())).then((t => {    if (t.hasOwnProperty("error")) throw "1" != t.error && alert(t.error), new Error(t.error);    return Object.prototype.hasOwnProperty.call(t, "source") && (r.source = t.source), Object.prototype.hasOwnProperty.call(t, "target") && (r.target = t.target), Object.prototype.hasOwnProperty.call(t, "translatedText") && (r.text = e, r.translatedText = t.translatedText), t  })).catch((e => {}))}

Persistent UUID helper

translate/translate-sl.js
function n() {  return null == localStorage.getItem("uuid") && localStorage.setItem("uuid", self.crypto.randomUUID()), localStorage.getItem("uuid")}
Destination contacted by the translation path
    • sellerlife.co.kr

    Receives the translation POST containing selected text and the persistent extension UUID headers.

Updated 30 September 2026cgococegfcmmfcjggpgelfbjkkncclkf