Is Extract Text from Image safe?
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.…
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
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 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.
- Storage keysupabase.auth.token
Any key name the page chooses -- there is no allow-list restricting which chrome.storage.sync entries can be touched.
- Storage valueCANARY_SUPA_TOKEN_7f3e91
The value stored or returned for that key, which the live test showed round-trips unchanged.
- ActionsetItem
Which operation the page requested: write a key, read a key, or delete a key.
Message relay accepting arbitrary storage keys from matching pages
onMessageExternal listener and setItem/getItem handlers
js/extension-worker.js:726-772chrome.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' }); }});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
{ "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"}- 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
You install Extract Text from Image for the first time.
chrome.runtime.onInstalled fires with reason set to INSTALL.
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.
- Install event nameinstall
Tells onlineapp.pro that a new install just happened.
- Extension IDadkbpbalabenjlfngiefoifoebjpbjjl
Identifies exactly which Chrome Web Store listing this install came from.
- Persistent device IDf9b3330f-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 ID93
A build-time constant identifying which distribution channel this copy of the extension was published through.
200 OK. The request body itself is the evidence of what leaves the device on install.
- Content-Type
- application/json
{ "event": "install", "wallId": 93, "extensionId": "adkbpbalabenjlfngiefoifoebjpbjjl", "userId": "f9b3330f-befd-4668-834d-baa1298973f6"}Install event handler and tracking beacon in the shipped extension
onInstalled listener firing the beacon
js/extension-worker.js:635-648chrome.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-717function 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); }); } });}- onlineapp.pro
Receives the install event, extension ID, and persistent device UUID via /api/track-event.