Is Visualping: Website change detection, monitoring and alerts safe?

High risk

Visualping: Website change detection, monitoring and alerts is high risk. Setting up server-side monitoring makes Visualping read the tab's entire localStorage and send it to api.visualping.io as a setItem() replay script.…

visualping.iov4.12.5Chrome Web Store
77Risk
Who publishes it

WEBMONITORING TECHNOLOGIES INC. - 1 other listing 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
visualping.io
Declared legal entity
WEBMONITORING TECHNOLOGIES INC.
Registered address
c/o WeWork, 555 Burrard St 1st Floor, Vancouver, BC V7X 1M8, CA
Registered contact
Serge Salager

Same store account

1 other listing published from this account, 100k+ users between them, none of them carrying a finding.

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.

visualping.io
Also called by 1 other listing: AEM Chrome Extension - AEM Assist

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

Publishers can request a review.

Findings

Active tab's full localStorage sent to api.visualping.io on Server-tab job setup

HighunwantedCWE-200Dynamic sandbox

Setting up server-side monitoring makes Visualping read the tab's entire localStorage and send it to api.visualping.io as a setItem() replay script.

What actually happens

You did this

You set up server-side monitoring for a page you're signed into.

In the popup you switch to the Server tab, enter an email, and click Start Monitoring.

The extension did this

The extension reads the tab's entire localStorage and sends it to Visualping's API.

It injects JSON.stringify(localStorage), rebuilds every entry as setItem() calls, and POSTs them inside the new monitoring job.

Captured request

POSThttps://api.visualping.io/v2/jobs/

Observed during dynamic analysis: the POST carried a 'script' preaction (~2,880 chars, 24 localStorage.setItem calls) reproducing the active tab's full localStorage. A planted marker value was present, confirming the storage leaves the device. Real values are redacted here.

Headers
Content-Type
application/json
X-Api-Client
vp-chrome-extension-<digest>
Body
{  "active": true,  "origin": "chrome",  "email": "testuser@example.com",  "url": "https://chatgpt.com/",  "mode": "VISUAL",  "target_device": "1",  "preactions": {    "active": true,    "actions": [      {        "script": "localStorage.setItem(\"oai/apps/hasSeenOnboarding\", \"<redacted>\"); \nlocalStorage.setItem(\"statsig.stable_id\", \"<redacted>\"); \nlocalStorage.setItem(\"canary_ls_key\", \"PARROT_LS_67890\"); \n"      },      {        "refresh": true      },      {        "wait": "5"      }    ]  }}

What's stored on your device

The page's localStorage is read and rebuilt server-side, often holding login tokens; a planted marker confirmed it leaves the device.

Location
Active tab localStorage (read via injected JSON.stringify(localStorage))
Contents
{  "canary_ls_key": "PARROT_LS_67890 (planted marker, confirmed transmitted)",  "statsig.stable_id": "<redacted>",  "oai/apps/hasSeenOnboarding": "<redacted>",  "<auth/session keys present on the page>": "<redacted>"}

The code that does this

localStorage capture and script-preaction build

Readable version
async function dl() {  // read the active tab's full localStorage  return new Promise(resolve => {    chrome.tabs.query({ active: true, currentWindow: true }, ([tab]) => {      chrome.scripting.executeScript({        target: { tabId: tab.id },        func: () => JSON.stringify(localStorage)   // every key/value      }, ([res]) => resolve(JSON.parse(res.result)));    });  });}function ml(store) {  let script = '';  Object.keys(store)    .filter(k => JSON.stringify(store[k]).length < 2300)  // skip oversize entries    .forEach(k => {      script += `localStorage.setItem("${k}", ${JSON.stringify(store[k])}); \n`;    });  return script;}function fl(store) {  const script = ml(store);  return script === '' ? [] : [{ script }, { refresh: true }, { wait: '5' }];}// fl(localStorage) is merged into preactions.actions and POSTed to api.visualping.io/v2/jobs/

Where the localStorage is sent

    • api.visualping.io

    Visualping's backend (Visualping Technologies Inc.). Receives the job containing the tab's localStorage as a setItem() replay script used to recreate your storage state.

Monitored site cookies sent to api.visualping.io on Server-tab job setup

HighunwantedCWE-522Dynamic sandbox

During server-side monitoring, Visualping reads the page's cookies and sends them to api.visualping.io, which replays them to load the page.

What actually happens

You did this

You set up server-side monitoring for a page you're signed into.

In the popup you switch to the Server tab, enter an email, and click Start Monitoring.

The extension did this

The extension reads that page's cookies and sends their values to Visualping's API.

It collects the root-path cookies for the page's domain and POSTs them inside the new monitoring job.

Captured request

POSThttps://api.visualping.io/v2/jobs/

Observed during dynamic analysis: the POST carried 24 root-path cookie objects for the monitored domain. A planted marker cookie was present in the body, confirming the cookies leave the device. Real session cookies were captured in plaintext; their values are redacted here.

Headers
Content-Type
application/json
X-Api-Client
vp-chrome-extension-<digest>
Body
{  "active": true,  "origin": "chrome",  "email": "testuser@example.com",  "url": "https://chatgpt.com/",  "interval": "60",  "mode": "VISUAL",  "target_device": "1",  "preactions": {    "active": true,    "actions": [      {        "cookie": {          "field": "__Host-next-auth.csrf-token",          "value": "<redacted>",          "domain": "chatgpt.com"        }      },      {        "cookie": {          "field": "oai-did",          "value": "<redacted>",          "domain": "chatgpt.com"        }      },      {        "cookie": {          "field": "_cfuvid",          "value": "<redacted>",          "domain": "chatgpt.com"        }      },      {        "cookie": {          "field": "canary_cookie",          "value": "BIRD_COOKIE_12345",          "domain": "chatgpt.com"        }      }    ]  }}

Cookie fields placed in the job body

  • Authentication / CSRF cookie
    __Host-next-auth.csrf-token = <redacted>

    Carries your signed-in state for the site. Whoever holds it can act as you on that site without your password.

  • Device / user identifier cookie
    oai-did = <redacted>

    Ties activity back to your account or browser on that site.

  • Other root-path cookies
    _cfuvid = <redacted>

    Every cookie set at the domain's root path is included, not just the ones strictly needed to load the page.

The code that does this

Cookie collection and transmission

Readable version
async function pl(e) {  const t = cl(e);                       // domain of the monitored URL  return (await chrome.cookies.getAll({ domain: t }))    .filter(c => c.name && typeof c.value === 'string' && c.domain)    .filter(c => c.path === '/')          // keep root-path cookies    .map(c => ({ cookie: { field: c.name, value: c.value, domain: c.domain } }));}// gl(): on Server-tab job creationPromise.all([pl(e.url), dl()]).then(([cookies, ls]) => {  let actions = [...cookies, ...fl(ls)];   // cookies + localStorage preactions  const job = {    active: true, origin: 'chrome', email: e.email, url: e.url,    mode: 'VISUAL', target_device: '1',    preactions: { active: true, actions }  // cookie values travel here  };  $.ajax({    url: 'https://api.visualping.io/v2/jobs/',    type: 'POST',    data: JSON.stringify(job),    headers: { 'Content-Type': 'application/json',               'X-Api-Client': 'vp-chrome-extension-' + digest }  });});

Where the cookies are sent

    • api.visualping.io

    Visualping's backend (Visualping Technologies Inc.). Receives the monitoring job with the site's cookie values and replays them server-side to load the page in your session.

Updated 30 September 2026fbhjaehnpccniaiedddkbdhgicmcmgng