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.
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.
| Field | Value | Why it matters | |
|---|---|---|---|
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. |
Message relay accepting arbitrary storage keys from matching pages
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' });
}
});A marker value written and read back via the setItem/getItem relay during testing, in the bucket Chrome syncs to every device.
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
Same relay access as onlineapp.pro.
- 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.
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.
| Field | Value | Why it matters | |
|---|---|---|---|
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. |
| 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
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) {
}
});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);
});
}
});
}- onlineapp.pro
Receives the install event, extension ID, and persistent device UUID via /api/track-event.