Is Emily safe?
Emily reads full page text, Gmail threads, and LinkedIn posts from your browser and sends the content to api.meetemily.ai to generate AI replies.
When you invoke Emily's AI features, the extension extracts the full visible text of your active tab—including Gmail email threads and LinkedIn post content—and transmits it to api.meetemily.ai over a Socket.IO WebSocket connection authenticated with a Firebase token. Your email address, user ID, and current page URL are also sent to PostHog analytics on every AI widget interaction. A content script running on all pages acts as a relay bridge, and any in-page script can use this bridge to query the titles and URLs of all your open tabs.
Who publishes itai - no other listings under this identity
ai - no other listings under this identity
What this publisher told the store about itself, and the other listings that told it the same thing.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Active Tab Full-Text Extracted and Posted to api.meetemily.ai
Any AI feature in Emily's side panel, summarise, translate, chat with page, analyse data, collects all visible page text via script, sent to api.meetemily.ai over an authenticated WebSocket.
Happens on any site, not just Emily-related ones.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-200
- Source
- Dynamic sandbox
You click a Summarise, Translate, Chat, or Analyse button in the Emily side panel on any web page.
Emily injects a script into your current tab, extracts the entire visible page text (document.body.innerText), and transmits it to api.meetemily.ai via an authenticated WebSocket.
Applies to any site, banking, HR portals, internal tools, webmail, or anything else open in the active tab.
The executeScript call that reads the active tab's full text
service_worker.js — /tab-content handler
// service_worker.js — message handlerelse if (path === '/tab-content') { const { tabId } = msg.payload; const [result] = await chrome.scripting.executeScript({ target: { tabId, allFrames: false }, func: () => ({ innerText: document.body.innerText, innerHTML: document.body.innerHTML }) }); if (result.result) { respond({ innerText: result.result.innerText, innerHTML: result.result.innerHTML }); }}js/529.js module 69625 — general page extraction
// js/529.js module 69625 — getTabContent() — general-page branchconst [scriptResult] = await chrome.scripting.executeScript({ target: { tabId: activeTab.id, allFrames: false }, func: () => ({ innerText: document.body.innerText })});if (scriptResult.result) { return { innerText: scriptResult.result.innerText, title: activeTab.title ?? '', faviconUrl: activeTab.favIconUrl };}- Full visible page textdocument.body.innerText — e.g. complete text of an internal wiki page, HR portal, or banking dashboard
All text rendered in the active tab at the moment the AI feature is triggered.
- Page titleAcme Corp — Q2 2026 Performance Reviews
The <title> of the tab, sent as part of the prompt context.
- Extension prompt typesummarisePage
Which AI feature was triggered (summarisePage, translatePage, chatWithPage, etc.).
- Firebase auth tokeneyJhbGciOiJSUzI1NiIsImtpZCI6...
Bearer token used to authenticate the WebSocket session. Scoped to the signed-in Emily account.
- api.meetemily.ai
Emily's backend AI service. Receives full page text and returns generated AI responses. Operated by the Emily/Growth School developer.
Gmail Email Thread Text Read from DOM and Sent to api.meetemily.ai
Clicking Emily's AI Reply in a Gmail thread reads the email body text directly from the Gmail page and sends it to api.meetemily.ai to draft a reply, including the quoted thread text visible in the reply box.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-200
- Source
- Dynamic sandbox
You open a Gmail thread and click the Emily AI Reply button.
Emily reads the quoted email body from the Gmail DOM and sends it as prompt context to api.meetemily.ai/ai/completion.
The email thread text is embedded verbatim in the API request body under a <content> tag alongside the user's reply instructions.
How Gmail email content is collected and transmitted
Email body extracted from .gmail_quote
// embed_script.js — Gmail email text extraction (Oc component)const replyEditor = await waitForElement('[contenteditable="true"]', container);if (replyEditor) { const quotedEmail = await waitForElement('.gmail_quote', replyEditor); if (quotedEmail) { const emailText = quotedEmail.innerText; setPostText(emailText); // stored for use in API call }}Email text embedded in prompt and posted to api.meetemily.ai
// embed_script.js — API request construction (Ic component)const prompt = ` <basePrompt>${basePromptFromConfig}</basePrompt> here are the contents of the mails - <content>${emailText}</content> here are the instructions for how to generate the email reply - <instructions>${userInstructions}</instructions> please generate a email reply`;await api.getCompletion({ extensionPromptType: 'gmailAIReply', messages: [{ role: 'user', content: prompt }] });// → fetch POST to api.meetemily.ai/ai/completion- Quoted email thread textOn Mon, 2 Jun 2026, Alice Smith wrote: Please find the attached Q2 forecast...
The body of the email thread you are replying to, read from the .gmail_quote element.
- Reply instructionsWrite a polite follow-up asking for clarification on the budget figures
Any text the user typed into the instruction field before generating a reply.
- Firebase auth tokeneyJhbGciOiJSUzI1NiIsImtpZCI6...
Bearer token identifying the signed-in Emily account.
- api.meetemily.ai
Emily's AI backend. Receives the email thread text and returns a generated reply draft. Operated by the Emily/Growth School developer.
Active Tab Content Extracted via executeScript for AI Context on Any Page
Chat with Page, Summarise, and similar features inject a script collecting page text or HTML.
Docs fetches content by document ID; Sheets reads its sheet name and fetches data; other pages get full body text.
All sent to api.meetemily.ai.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-200
- Source
- Dynamic sandbox
You click an AI feature button in the Emily side panel while any page is open.
Emily checks the tab URL: Docs fetches content via api.meetemily.ai; Sheets reads sheet name and fetches data; other pages get full body text via executeScript, sent as context.
The capability applies to any site, banking portals, internal tools, HR systems, or any other open tab, not just Google Docs or Sheets.
The three-branch content extraction function from js/529.js
Deobfuscated getTabContent — all three extraction paths
// js/529.js module 69625 — getTabContent(setPublicMessage)async function getTabContent(setPublicMessage) { const [activeTab] = await chrome.tabs.query({ active: true, currentWindow: true }); const { id: tabId, url, title, favIconUrl } = activeTab; if (isGoogleDoc(url)) { // Branch 1: fetch document content from api.meetemily.ai const docId = extractDocId(url); const { output } = await api.getGoogleDocData({ documentId: docId }); return { innerText: output, title, favIconUrl }; } else if (isGoogleSheet(url)) { // Branch 2: read active sheet name via DOM, then fetch sheet data const sheetId = extractSheetId(url); const [{ result }] = await chrome.scripting.executeScript({ target: { tabId, allFrames: false }, func: () => ({ innerHTML: document.body.innerHTML }) // reads sheet tab name }); const activeSheetName = cheerio(result.innerHTML)('.docs-sheet-active-tab .docs-sheet-tab-name').text(); const { values } = await api.getGoogleSheetDataRaw({ spreadsheetId: sheetId, range: activeSheetName }); return { innerText: '', file: csvFile(values, title), title, favIconUrl, url }; } else { // Branch 3: extract full body text from any other page const [{ result }] = await chrome.scripting.executeScript({ target: { tabId, allFrames: false }, func: () => ({ innerText: document.body.innerText }) }); if (result) return { innerText: result.innerText, title, favIconUrl }; }}- Generic page, full body textComplete text of an internal HR portal or banking dashboard
All visible text from any website, extracted via document.body.innerText. Any open tab qualifies.
- Google Sheets, active sheet HTMLVisible HTML fragment including .docs-sheet-active-tab class
Full document.body.innerHTML of the Sheets page, used to locate the active tab name.
- Google Sheets, spreadsheet dataSheet1: [["Name","Salary"],["Alice","95000"],["Bob","87000"]]
Cell values from the active sheet range, fetched from api.meetemily.ai using the spreadsheet ID.
- Google Docs, document contentComplete text of a private Google Doc
Full document text fetched from api.meetemily.ai using the document ID extracted from the URL.
- Tab titleQ2 2026 Headcount Plan - Acme Corp
The title of the active tab, included as context in all branches.
- api.meetemily.ai
Emily's AI backend. Receives page content in all three extraction paths and returns AI-generated responses. Operated by the Emily/Growth School developer.
+1 more finding not shown
What it can do
Permissions this extension asks for, as declared in version 1.7.14. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.
Read and change your data on every secure site you visit
https://*/*
Read and change your data on every site you visit
http://*/*
Show a panel beside the page
sidePanel
Run its own code inside the pages you visit
scripting
Act on the current tab, but only after you click the extension
activeTab
See the address and title of every tab you have open
tabs
Store data in your browser
storage
Where it sends data
Destinations our analysis observed Emily contacting. Sending data somewhere is not a finding on its own - an extension that syncs your settings has to talk to its own server - but it is where your data can go, and who else it goes to.
- us.i.posthog.com
Emily sends data to us.i.posthog.com. 24 other extensions we have analysed send data here.
- api.meetemily.ai
Emily sends data to api.meetemily.ai. No other extension we have analysed sends data here.