Is Hana Wallet safe?
Hana Wallet is medium risk. Hana Wallet looks up your public IP address and reads a persistent device ID, then sends both to Amplitude's analytics API on install and again each time you open the wallet.
Who publishes itHana Tech Pty Ltd - no other listings under this identity
Hana Tech Pty Ltd - no other listings under this identity
What this publisher told the store about itself, and the other listings that told it the same thing.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Hana Wallet sends a persistent device ID and your public IP to Amplitude
Hana Wallet looks up your public IP address and reads a persistent device ID, then sends both to Amplitude's analytics API on install and again each time you open the wallet.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-359
- Source
- Dynamic sandbox
You install Hana Wallet, or open its popup, side panel, or main tab.
No wallet action, such as connecting to a site or sending funds, is required.
The background script looks up your public IP address and sends it, together with a persistent device ID, to Amplitude's analytics API.
The same report fires again on every later app load, not just the first install.
- Persistent device ID7d145bfe-cc78-42cc-aa35-c4355d87253f
A UUID generated once and saved in the extension's local storage, tying every future event back to this exact install.
- Your public IP address187.40.254.11
Looked up from a separate IP service just before the event is sent, then attached to the analytics record.
- Event nameApp Loaded
Marks what triggered the report, such as installing the extension or opening the wallet UI.
- Extension version5.13.10
Lets Amplitude segment events by the exact build you're running.
- Platform tagchrome-extension
Always reports as a Chrome extension, separating this install from Hana's mobile app in Amplitude.
- Content-Type
- application/json
{ "api_key": "<redacted>", "events": [ { "device_id": "7d145bfe-cc78-42cc-aa35-c4355d87253f", "event_type": "App Loaded", "app_version": "5.13.10", "platform": "chrome-extension", "ip": "187.40.254.11" } ]}Shipped background script vs. the same code reformatted for readability
Same functions, whitespace restored
background.jsasync function nt() { const e = await X.DT.getItem(q.AQ.USER_ID); if (!e) { const e = rt(); return await X.DT.setItem(q.AQ.USER_ID, e), e } return e } const it = [{ name: "Ipify", url: "https://api.ipify.org?format=json", parseResponse: e => e.ip }, { name: "IPinfo.io", url: "https://ipinfo.io/json", parseResponse: e => e.ip }, { name: "db-ip.com", url: "https://api.db-ip.com/v2/free/self", parseResponse: e => e.ipAddress }]; async function at(e) { try { const t = await fetch(e.url); if (!t.ok) throw new Error(`HTTP error! status: ${t.status}`); const r = await t.json(); return e.parseResponse(r) } catch (t) { return console.debug(`Error fetching IP from ${e.name}:`, t), null } } async function ot() { for (const e of it) { const t = await at(e); if (t) return { service: e.name, ip: t } } throw new Error("Failed to retrieve IP from all services") } let st = null; async function ct() { const e = st || await async function() { try { const e = await X.DT.getItem("ip_cache"); return e ? JSON.parse(e) : null } catch (e) { return console.debug("Could not retrieve IP from storage:", e), null } }(); if (e && Date.now() - e.timestamp < 36e5) return e.ip; try { const e = await ot(); return st = { ip: e.ip, timestamp: Date.now() }, function(e) { try { X.DT.setItem("ip_cache", JSON.stringify(e)) } catch (e) { console.debug("Could not save IP to storage:", e) } }(st), st.ip } catch (e) { return null } } async function dt(e, t = {}) { if (!q.HX) return void console.error("Amplitude API key is not properly initialized."); const r = await nt(), n = await ct(), i = { device_id: r, event_type: e, event_properties: t, time: Date.now(), app_version: q.gv, platform: "chrome-extension" }; n && (i.ip = n); try { const e = await fetch("https://api2.amplitude.com/2/httpapi", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ api_key: q.HX, events: [i] }) }); if (!e.ok) { const t = await e.text(); console.error("Amplitude Track API error:", e.status, t) } } catch (e) { console.error("Failed to send event to Amplitude:", e) } }- api2.amplitude.com
Receives the device ID, IP, and event metadata. Amplitude is a third-party product-analytics vendor, not part of Hana's own infrastructure.
- api.ipify.org
Primary IP-lookup service queried before each Amplitude event; returns the caller's public IP.
- ipinfo.io
First fallback IP-lookup service if ipify does not respond.
- api.db-ip.com
Second fallback IP-lookup service if both ipify and ipinfo fail.