Is 스마트스토어 쿠팡 분석 - SMART DATA 스마트데이터 safe?
SMART DATA sends buyer PII and customs codes to unipass.customs.go.kr via a hardcoded API key, and sends session data over plaintext HTTP.
The extension iterates Naver SmartStore orders and sends each recipient's name, phone number, and Korean customs clearance code (개인통관고유부호) to the Korean Customs Service API with a hardcoded authentication key embedded in the bundle. Authentication checks and usage quota updates are sent to the extension's backend over an unencrypted HTTP connection. The extension also reads all browser cookies and removes session cookies for smartstore.naver.com and brand.naver.com when entering anonymous API mode.
Who publishes itRUBYDATALAB - 3 other listings from the same operator, none carrying a finding
RUBYDATALAB - 3 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.
Same store account
3 other listings published from this account, 21k+ users between them, none of them carrying a finding.
Shared hosts - 2 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
Buyer customs details sent to Unipass
The customs-code confirmation workflow builds GET requests to the Korean Customs Unipass endpoint with buyer details in the query string: crkyCn API key, clearance code, recipient name, phone, from popup fields or the SmartStore order page.
What actually happens
You run the customs-code confirmation workflow.
The extension sends buyer customs details to Unipass using an API key embedded in the bundle.
The automated order-grid flow retries the lookup with recipient and buyer phone/name combinations when needed.
Captured request
XML response parsed by the extension
Query-string fields sent to the customs endpoint
- Bundled API keyq220h210p071h371l060m020c3
Anyone with the extension package can read the API credential used for the customs lookup.
- Recipient nameKim Minseo
This identifies the person whose customs clearance record is being checked.
- Customs clearance codeP123456789012
This links the lookup to a Korean personal customs clearance record.
- Phone number01012345678
This adds another direct identifier to the customs lookup.
The code that does this
Customs lookup functions and the embedded API key
Order-grid customs verification
popup.jsasync function confirmnaverpcc() { let [e] = await chrome.tabs.query({ active: !0, currentWindow: !0 }); if (!e.url.includes("sell.smartstore.naver.com")) return void alert("스마트스토어 발주(주문)확인/발송관리 메뉴에서 실행해 주세요"); let t = await chrome.scripting.executeScript({ target: { tabId: e.id }, func: async function() { var e = document.querySelector("#__delegate").contentDocument.documentElement.querySelector(".tui-grid-rside-area"); if (e) { let t = function(e) { let t = [], r = [], n = e.querySelectorAll("th"); for (let e = 0; e < n.length; e++) t.push(n[e].textContent.trim()); let a = e.querySelectorAll("tr"); for (let e = 1; e < a.length; e++) { let n = a[e].querySelectorAll("td"), o = {}; for (let e = 0; e < t.length; e++) o[t[e]] = n[e].textContent.trim(); r.push(o) } return r }(e); return t } return [] } }); var r = t[0].result; if (console.log(r), 0 != r.length) if (r[0].수취인명 && r[0].개인통관고유부호 && r[0].수취인연락처1 && r[0].구매자명 && r[0].구매자연락처) for (var n = 0; n < r.length; n++) { var a = await confirmpccfor(r[n].수취인명, r[n].개인통관고유부호, r[n].수취인연락처1), o = a.error; a.res ? c(n, "green", "일치", e) : r[n].수취인연락처2 && r[n].수취인연락처1 !== r[n].수취인연락처2 && (a = await confirmpccfor(r[n].수취인명, r[n].개인통관고유부호, r[n].수취인연락처2)).res ? c(n, "yellow", "수취인-수취인연락처2-개인통관고유부호 일치", e) : (a = await confirmpccfor(r[n].구매자명, r[n].개인통관고유부호, r[n].수취인연락처1)).res ? c(n, "yellow", "구매자명-수취인연락처1-개인통관고유부호 일치", e) : (a = await confirmpccfor(r[n].구매자명, r[n].개인통관고유부호, r[n].구매자연락처)).res ? c(n, "yellow", "구매자명-구매자연락처-개인통관고유부호 일치", e) : r[n].수취인연락처2 && r[n].수취인연락처1 !== r[n].수취인연락처2 && (a = await confirmpccfor(r[n].구매자명, r[n].개인통관고유부호, r[n].수취인연락처2)).res ? c(n, "yellow", "구매자명-수취인연락처2-개인통관고유부호 일치", e) : c(n, "red", o, e) } else alert("수취인명, 개인통관고유부호, 수취인연락처1, 구매자명, 구매자연락처를 조회항목에 추가한 후 실행해 주세요"); else alert("개인통관 고유부호를 검증할 내역이 없습니다. \n스마트스토어 발주(주문)확인/발송관리 메뉴에서 실행해 주세요"); async function c(e, t, r, n) { chrome.scripting.executeScript({ target: { tabId: n.id }, func: function(e, t, r) { var n = document.querySelector("#__delegate").contentDocument.documentElement.querySelector(".tui-grid-lside-area"); n.querySelectorAll("th")[1].outerHTML = '\n <th data-column-name="productOrderNo" class="tui-grid-cell tui-grid-cell-head" height="48" colspan="2" rowspan="1">\n <div class="_1-P09c3QA5" data-type="PRODUCT_ORDER_ID" data-direction="">\n <span class="_1-P09c3QA5" style="text-decoration: underline; pointer-events: none;">개인통관고유부호 검증결과</span>\n <span class="_1-P09c3QA5" style="color: #9299aa; pointer-events: none;"></span>\n </div>\n </th>\n '; let a = n.querySelectorAll("tr")[e + 1].querySelectorAll("td"); a[1].outerHTML = "red" == t ? '\n <td align="center" colspan="2" class="" data-edit-type="normal" data-row-key="0" data-column-name="productOrderNo">\n <div class="tui-grid-cell-content" style="background-color: ' + t + '">\n <p style="color:yellow">' + r + "</p>\n </div>\n </td>\n " : "yellow" == t ? '\n <td align="center" colspan="2" class="" data-edit-type="normal" data-row-key="0" data-column-name="productOrderNo">\n <div class="tui-grid-cell-content" style="background-color: ' + t + '">\n <p style="color:black">' + r + "</p>\n </div>\n </td>\n " : '\n <td align="center" colspan="2" class="" data-edit-type="normal" data-row-key="0" data-column-name="productOrderNo">\n <div class="tui-grid-cell-content" style="background-color: ' + t + '">\n <p style="color:white">' + r + "</p>\n </div>\n </td>\n " }, args: [e, t, r] }) }}Lookup helper with hardcoded API key
popup.jsasync function confirmpccfor(e, t, r) { var n = "https://unipass.customs.go.kr:38010/ext/rest/persEcmQry/retrievePersEcm?crkyCn=q220h210p071h371l060m020c3" + ("&persEcm=" + t + "&pltxNm=" + e + "&cralTelno=" + r.toString().replaceAll("-", "")), a = await fetch(n), o = await a.text(); var c = xmlToObject((new DOMParser).parseFromString(o, "text/xml")); return console.log(c), "1" == c.persEcmQryRtnVo.tCnt ? { res: !0 } : c.persEcmQryRtnVo.persEcmQryRtnErrInfoVo.errMsgCn ? { res: !1, error: c.persEcmQryRtnVo.persEcmQryRtnErrInfoVo.errMsgCn.replace("납세의무자명(pltxNm) 파라미터가 깨질경우 UTF-8로 변환하여 실행하십시오.", "").replace("입력하신 ", "").trim() } : { res: !1, error: c.persEcmQryRtnVo.persEcmQryRtnErrInfoVo[0].errMsgCn.replace("납세의무자명(pltxNm) 파라미터가 깨질경우 UTF-8로 변환하여 실행하십시오.", "").replace("입력하신 ", "").trim() }}Manual popup lookup
popup.jsasync function confirmpccfor(e, t, r) { var n = "https://unipass.customs.go.kr:38010/ext/rest/persEcmQry/retrievePersEcm?crkyCn=q220h210p071h371l060m020c3" + ("&persEcm=" + t + "&pltxNm=" + e + "&cralTelno=" + r.toString().replaceAll("-", "")), a = await fetch(n), o = await a.text(); var c = xmlToObject((new DOMParser).parseFromString(o, "text/xml")); return console.log(c), "1" == c.persEcmQryRtnVo.tCnt ? { res: !0 } : c.persEcmQryRtnVo.persEcmQryRtnErrInfoVo.errMsgCn ? { res: !1, error: c.persEcmQryRtnVo.persEcmQryRtnErrInfoVo.errMsgCn.replace("납세의무자명(pltxNm) 파라미터가 깨질경우 UTF-8로 변환하여 실행하십시오.", "").replace("입력하신 ", "").trim() } : { res: !1, error: c.persEcmQryRtnVo.persEcmQryRtnErrInfoVo[0].errMsgCn.replace("납세의무자명(pltxNm) 파라미터가 깨질경우 UTF-8로 변환하여 실행하십시오.", "").replace("입력하신 ", "").trim() }}External destination used by this workflow
- unipass.customs.go.kr
Korean Customs Unipass personal customs-code lookup endpoint receiving the query-string fields.
Naver session cookies removed before analysis
Starting review or option analysis runs a cookie cleanup before fetching Naver data: it lists cookies, checks SmartStore domains, removes matches for smartstore.naver.com/brand.naver.com.
One test run missed this; later proof confirmed it.
What actually happens
You start review or option analysis from the extension popup.
The extension removes Naver store cookies before continuing with the analysis workflow.
The affected domains are smartstore.naver.com and brand.naver.com.
Cookie fields affected by the cleanup path
- Cookie domainsmartstore.naver.com
This decides which signed-in Naver store session can be removed from your browser.
- Cookie nameNID_AUT
The extension reuses each matching cookie name when it asks Chrome to remove the cookie.
- Removal URLhttps://brand.naver.com
The cleanup is applied to Naver SmartStore and Brand Naver cookie stores.
The code that does this
Cookie cleanup and the review-analysis entry point
Popup cookie cleanup
popup.jsasync function secretOn() { var e = await chrome.cookies.getAll({}); for (var t of e) t.domain.includes("smartstore.naver.com") && (await chrome.cookies.remove({ name: t.name, url: "https://smartstore.naver.com" }), await chrome.cookies.remove({ name: t.name, url: "https://brand.naver.com" })); return console.log("secret On"), "시크릿 모드 On"}Popup review parsing calls cleanup first
popup.jsasync function reviewparsing() { await secretOn(), await async function() { let [e] = await chrome.tabs.query({ active: !0, currentWindow: !0 }), t = await chrome.scripting.executeScript({ target: { tabId: e.id }, world: "MAIN", func: fetchpageinfo, args: [e.url] }); if (console.log(t[0].result), !t[0]?.result) return; var r = e.url, n = t[0].result.merchantno, a = t[0].result.productno, o = r.slice(0, r.search(".com") + 4); o.search("shopping") > 0 || (o.search("brand") > 0 ? o += "/n" : o += "/i"); var c = o + "/v1/contents/reviews/query-pages", s = { headers: { accept: "application/json, text/plain, */*", "accept-language": "ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7", "content-type": "application/json", priority: "u=1, i", "sec-ch-ua": '"Not/A)Brand";v="8", "Chromium";v="126", "Google Chrome";v="126"', "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": '"Windows"', "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-origin", "x-client-version": "20240729102925" }, referrerPolicy: "no-referrer-when-downgrade", body: '{"checkoutMerchantNo":' + n + ',"originProductNo":' + a + ',"page":1,"pageSize":20,"reviewSearchSortType":"REVIEW_RANKING"}', method: "POST", mode: "cors", credentials: "include" }; const i = (await chrome.scripting.executeScript({ target: { tabId: e.id }, func: fetchScriptingToJson, args: [c, s] }))[0].result; maxpage = i.totalPages, lastpage = i.totalPages; for (var l = 0; l < maxpage; l++) { await sleep(500); r = o + "/v1/contents/reviews/query-pages"; s = { headers: { accept: "application/json, text/plain, */*", "accept-language": "ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7", "content-type": "application/json", priority: "u=1, i", "sec-ch-ua": '"Not/A)Brand";v="8", "Chromium";v="126", "Google Chrome";v="126"', "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": '"Windows"', "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-origin", "x-client-version": "20240729102925" }, referrerPolicy: "no-referrer-when-downgrade", body: '{"checkoutMerchantNo":' + n + ',"originProductNo":' + a + ',"page":' + (l + 1) + ',"pageSize":30,"reviewSearchSortType":"REVIEW_RANKING"}', method: "POST", mode: "cors", credentials: "include" }, document.querySelector("#reviewprogress").innerText = parseInt((l + 1) / maxpage * 100), document.querySelector("#optionprogress").innerText = parseInt((l + 1) / maxpage * 100); var d = await chrome.scripting.executeScript({ target: { tabId: e.id }, func: fetchScriptingToText, args: [r, s] }), u = await d[0].result; if (console.log(u), u.length < 10) return; { const e = JSON.parse(u); for (var m of e.contents) reviewdata.push({ "구매id": m.writerId, "리뷰날짜": m.createDate, "구매옵션": m.productOptionContent, "리뷰내용": m.reviewContent, "리뷰점수": m.reviewScore }) } } }()}Background retry path also clears SmartStore cookies
background.jsasync function secretOn() { var e = await chrome.cookies.getAll({}); for (var t of (console.log(e), e)) t.domain.includes("smartstore.naver.com") && (await chrome.cookies.remove({ name: t.name, url: "https://smartstore.naver.com" }), await chrome.cookies.remove({ name: t.name, url: "https://brand.naver.com" })); return console.log("secret On"), "시크릿 모드 On"}The code that does this
Manifest grants cookie access across every host
{"update_url": "https://clients2.google.com/service/update2/crx", "name": "스마트스토어 쿠팡 분석 - SMART DATA 스마트데이터", "description": "스마트스토어 쿠팡 이커머스 통합 분석 솔루션", "version": "3.8", "manifest_version": 3, "background": { "service_worker": "background.js" }, "permissions": ["activeTab", "scripting", "tabs","cookies","declarativeNetRequest"], "action": { "default_popup": "popup.html", "default_icon": { "16": "/images/icon.png", "32": "/images/icon.png", "48": "/images/icon.png", "128": "/images/icon.png" } }, "icons": { "16": "/images/icon.png", "32": "/images/icon.png", "48": "/images/icon.png", "128": "/images/icon.png" }, "content_scripts": [ { "matches": ["*://*/*"], "match_origin_as_fallback": true, "js": ["script.js"] } ], "host_permissions": [ "*://*/*" ], "declarative_net_request": { "rule_resources": [{ "id": "ruleset_1", "enabled": true, "path": "rules.json" }] } }What it can do
Permissions this extension asks for, as declared in version 3.8. 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 every site you visit
*://*/*
Act on the current tab, but only after you click the extension
activeTab
Run its own code inside the pages you visit
scripting
See the address and title of every tab you have open
tabs
Read and change cookies, including the ones that keep you signed in
cookies
Block and redirect the requests your browser makes
declarativeNetRequest
Where it sends data
Destinations our analysis observed 스마트스토어 쿠팡 분석 - SMART DATA 스마트데이터 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.
- smartdata-env.eba-uqvs9y7q.ap-northeast-2.elasticbeanstalk.com
스마트스토어 쿠팡 분석 - SMART DATA 스마트데이터 sends data to smartdata-env.eba-uqvs9y7q.ap-northeast-2.elasticbeanstalk.com. No other extension we have analyzed sends data here.
- unipass.customs.go.kr
스마트스토어 쿠팡 분석 - SMART DATA 스마트데이터 sends data to unipass.customs.go.kr. No other extension we have analyzed sends data here.