Is Extract Text from Image safe?

Medium risk

Extract Text from Image is medium risk. sendMessage {source:'supabase-auth-adapter', action:'setItem', data:{key,value}} writes into chrome.storage.sync unrestricted; getItem reads it back. This syncs across account devices. The listener only checks sender URL for a substring.…

kitos122023v2.3.0Chrome Web Store
49Risk

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

Publishers can request a review.

Findings

onlineapp.pro pages can read and write any chrome.storage.sync key

sendMessage {source:'supabase-auth-adapter', action:'setItem', data:{key,value}} writes into chrome.storage.sync unrestricted; getItem reads it back.

This syncs across account devices.

The listener only checks sender URL for a substring.

Severity
Medium unwanted
Type
Unexpected
CWE
CWE-200
Source
Dynamic sandbox
What actually happens
You did this

You visit a page whose URL contains 'onlineapp.pro' and it sends the extension a storage message.

The page calls chrome.runtime.sendMessage(extensionId, { source: 'supabase-auth-adapter', action: 'setItem', data: { key, value } }).

The extension did this

The extension writes that exact key and value into chrome.storage.sync with no restriction on which key is used.

chrome.storage.sync.set({ [key]: value }) runs directly on the caller-supplied key, then the entry syncs to every device on the account.

What the message relay lets a matching page read or write
  • Storage key
    supabase.auth.token

    Any key name the page chooses -- there is no allow-list restricting which chrome.storage.sync entries can be touched.

  • Storage value
    CANARY_SUPA_TOKEN_7f3e91

    The value stored or returned for that key, which the live test showed round-trips unchanged.

  • Action
    setItem

    Which operation the page requested: write a key, read a key, or delete a key.

The code that does this

Message relay accepting arbitrary storage keys from matching pages

Readable version

onMessageExternal listener and setItem/getItem handlers

js/extension-worker.js:726-772
chrome.runtime.onMessageExternal.addListener((message, sender, sendResponse) => {    if (        sender.url &&        (sender.url.includes('onlineapp.pro') ||            sender.url.includes('onlineapp.live') ||            sender.url.includes('onlineapp.stream'))    ) {        if (message.source === 'supabase-auth-adapter') {            switch (message.action) {                case 'getItem':                    try {                        const { key } = message.data;                        chrome.storage.sync.get(key, result => {                            if (chrome.runtime.lastError) {                                sendResponse({ status: 'error', message: chrome.runtime.lastError.message });                            } else {                                sendResponse({ status: 'success', value: result[key] || null });                            }                        });                        return true;                    } catch (error) {                        sendResponse({ status: 'error', message: error.message });                    }                    break;                case 'setItem':                    try {                        const { key, value } = message.data;                        chrome.storage.sync.set({ [key]: value }, () => {                            if (chrome.runtime.lastError) {                                sendResponse({ status: 'error', message: chrome.runtime.lastError.message });                            } else {                                sendResponse({ status: 'success' });                                notifyConnectedClients({ type: 'storage_update', action: 'set', key, value, timestamp: Date.now() });                            }                        });                        return true;                    } catch (error) {                        sendResponse({ status: 'error', message: error.message });                    }                    break;            }        }    } else {        sendResponse({ status: 'error', message: 'Unauthorized domain' });    }});
What's stored on your device

A marker value written and read back via the setItem/getItem relay during testing, in the bucket Chrome syncs to every device.

Location
chrome.storage.sync, synced to every device on the signed-in Chrome account
Contents
{  "user_id": "f9b3330f-befd-4668-834d-baa1298973f6",  "installDate": "2026-08-01T12:00:00.000Z",  "pw-93-visitor-id": "f9b3330f-befd-4668-834d-baa1298973f6",  "da_verify_canary_key": "CANARY_SUPA_TOKEN_7f3e91"}
Pages permitted to reach the storage relay
    • onlineapp.pro

    Any page whose URL contains this text can invoke the setItem/getItem/removeItem relay via chrome.runtime.onMessageExternal.

    • onlineapp.live
    • onlineapp.stream

    Same relay access as onlineapp.pro.

Install beacon sends a persistent device ID to onlineapp.pro

onInstalled POSTs an install event, extension ID, and random UUID to onlineapp.pro/api/track-event, no consent prompt.

The UUID is made once, stored as user_id/pw-93-visitor-id, and reused.

The listing claims no sensitive data is sent.

Severity
Medium unwanted
Type
Unexpected
CWE
CWE-200
Source
Dynamic sandbox
What actually happens
You did this

You install Extract Text from Image for the first time.

chrome.runtime.onInstalled fires with reason set to INSTALL.

The extension did this

The service worker immediately sends your install event and a persistent random ID to onlineapp.pro.

trackEvent('install') retrieves or generates a UUID via getUserId(), then POSTs it to https://onlineapp.pro/api/track-event.

Fields sent in the install-tracking request
  • Install event name
    install

    Tells onlineapp.pro that a new install just happened.

  • Extension ID
    adkbpbalabenjlfngiefoifoebjpbjjl

    Identifies exactly which Chrome Web Store listing this install came from.

  • Persistent device ID
    f9b3330f-befd-4668-834d-baa1298973f6

    A random ID made once at install and stored permanently, letting onlineapp.pro recognize this browser on future requests.

  • Distribution wall ID
    93

    A build-time constant identifying which distribution channel this copy of the extension was published through.

Captured request
POSThttps://onlineapp.pro/api/track-event

200 OK. The request body itself is the evidence of what leaves the device on install.

Headers
Content-Type
application/json
Body
{  "event": "install",  "wallId": 93,  "extensionId": "adkbpbalabenjlfngiefoifoebjpbjjl",  "userId": "f9b3330f-befd-4668-834d-baa1298973f6"}
The code that does this

Install event handler and tracking beacon in the shipped extension

Readable version

onInstalled listener firing the beacon

js/extension-worker.js:635-648
chrome.runtime.onInstalled.addListener((details) => {    if (details.reason === chrome.runtime.OnInstalledReason.INSTALL) {        chrome.tabs.create({            url: "/welcome.html",        });        trackEvent('install');        const installDate = new Date().toISOString();        chrome.storage.sync.set({ installDate });    } else if (details.reason === chrome.runtime.OnInstalledReason.UPDATE) {    }});

trackEvent and getUserId

js/extension-worker.js:685-717
function trackEvent(eventName, additionalData = {}) {    getUserId(userId => {        fetch('https://onlineapp.pro/api/track-event', {            method: 'POST',            headers: { 'Content-Type': 'application/json' },            body: JSON.stringify({                event: eventName,                wallId: parseInt('93'),                extensionId: chrome.runtime.id,                userId: userId,                ...additionalData,            }),        });    });}function getUserId(callback) {    chrome.storage.sync.get(['user_id'], result => {        if (result.user_id) {            callback(result.user_id);        } else {            const userId = crypto.randomUUID();            chrome.storage.sync.set({ user_id: userId, [`pw-93-visitor-id`]: userId }, () => {                callback(userId);            });        }    });}
Host receiving the install-tracking beacon
    • onlineapp.pro

    Receives the install event, extension ID, and persistent device UUID via /api/track-event.

Updated 30 September 2026adkbpbalabenjlfngiefoifoebjpbjjl