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
45Risk

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

Publishers can request a review.

Findings

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-200
SourceAI SANDBOX

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.

01EvidenceCAUSE EFFECT
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.

02EvidenceFIELD TABLE
What the message relay lets a matching page read or write
FieldValueWhy it matters
Storage key
supabase.auth.tokenAny key name the page chooses -- there is no allow-list restricting which chrome.storage.sync entries can be touched.
Storage value
CANARY_SUPA_TOKEN_7f3e91The value stored or returned for that key, which the live test showed round-trips unchanged.
Action
setItemWhich operation the page requested: write a key, read a key, or delete a key.
03EvidenceCODE COMPARE
The code that does this

Message relay accepting arbitrary storage keys from matching pages

What it actually does
onMessageExternal listener and setItem/getItem handlersjs/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' });
    }
});
04EvidenceSTORAGE DUMP
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.

Locationchrome.storage.sync, synced to every device on the signed-in Chrome account
Contents (JSON)
{
  "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"
}
05EvidenceTHIRD PARTY LIST
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

    Same relay access as onlineapp.pro.

  • onlineapp.stream

    Same relay access as onlineapp.pro.

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-200
SourceAI SANDBOX

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.

01EvidenceCAUSE EFFECT
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.

02EvidenceFIELD TABLE
Fields sent in the install-tracking request
FieldValueWhy it matters
Install event name
installTells onlineapp.pro that a new install just happened.
Extension ID
adkbpbalabenjlfngiefoifoebjpbjjlIdentifies exactly which Chrome Web Store listing this install came from.
Persistent device ID
f9b3330f-befd-4668-834d-baa1298973f6A random ID made once at install and stored permanently, letting onlineapp.pro recognize this browser on future requests.
Distribution wall ID
93A build-time constant identifying which distribution channel this copy of the extension was published through.
03EvidenceNETWORK CAPTURE
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-Typeapplication/json
Body
{
  "event": "install",
  "wallId": 93,
  "extensionId": "adkbpbalabenjlfngiefoifoebjpbjjl",
  "userId": "f9b3330f-befd-4668-834d-baa1298973f6"
}
04EvidenceCODE COMPARE
The code that does this

Install event handler and tracking beacon in the shipped extension

What it actually does
onInstalled listener firing the beaconjs/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 getUserIdjs/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);
            });
        }
    });
}
05EvidenceTHIRD PARTY LIST
Host receiving the install-tracking beacon
  • onlineapp.pro

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