Is Zapier Agents safe?
Zapier Agents is medium risk. Zapier Agents injects an active-tab script during the browser-context flow, returning page text, title, and URL to the Zapier Agents page. Testing did not observe this without login, but the code path is present in the shipped extension.…
Who publishes itZapier, Inc. - 1 other listing from the same operator, none carrying a finding
Zapier, Inc. - 1 other listing from the same operator, none carrying a finding
What this publisher told the store about itself, and the other listings that told it the same thing.
Same store account
1 other listing published from this account, 40k+ users between them, none of them carrying a finding.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Active-tab page text is relayed to Zapier Agents
Zapier Agents injects an active-tab script during the browser-context flow, returning page text, title, and URL to the Zapier Agents page.
Testing did not observe this without login, but the code path is present in the shipped extension.
What actually happens
You use the Zapier Agents side panel while browsing in an active tab.
The flow depends on Zapier authentication and the side panel being open.
The extension reads the active tab's visible page text, title, and URL and returns them to the Zapier Agents page.
The service worker sends getPageContent to active-tab-script.js and forwards the response back through the content-script message path.
Fields returned from the active tab
- Active tab URLhttps://example.com/account/settings
Shows the exact page address open in your active browser tab.
- Page titleAccount Settings
Identifies the page or document visible in the browser tab.
- Visible page textProject notes and account details visible on the page
Can include readable content from the active page, including private document, workspace, or account text.
- Google document textQuarterly planning notes from a Google Doc
When the active tab is a Google Doc, the extension can request document content through the Google Docs API.
- Google spreadsheet valuesThis text represents the values in the rows of a spreadsheet: [["Account","Owner"]]
When the active tab is a Google Sheet, the extension can request spreadsheet grid values through the Google Sheets API.
Captured request
Loaded as the Zapier Agents side-panel iframe; no request body is present for this navigation.
The code that does this
The service worker injects the active-tab reader and requests page content
Deobfuscated service-worker.js getBrowserContext handler
service-worker.jschrome.runtime.onMessage.addListener(((t, e, n) => {if ("getBrowserContext" === t) return async function() { const t = await vr(); return new Promise(((e, n) => { t.id ? chrome.tabs.sendMessage(t.id, "getPageContent", (function(r) { r ? e(r) : (t.url || e(void 0), je(`Unable to get page data from tab: ${t.url} (Last error: ${chrome.runtime.lastError?.message})`), n(new Error(`Unable to get page data from tab: ${t.url}`))) })) : n(new Error("No current tab")) }))}().then((t => { n(t)})).catch((() => { n("")})), !0}))Deobfuscated service-worker.js active-tab injection hooks
service-worker.jschrome.tabs.onActivated.addListener((async ({tabId: t}) => {if (t) { try { await chrome.scripting.executeScript({ target: { tabId: t }, files: ["active-tab-script.js"] }) } catch {} chrome.tabs.query({ active: !0, currentWindow: !0 }, (async ([t]) => { Sr(t.url?.includes("linkedin.com") ?? !1) }))}})), chrome.tabs.onUpdated.addListener(((t, e) => {(e.url || e.status) && chrome.tabs.query({ active: !0, currentWindow: !0}, (async ([e]) => { try { await chrome.scripting.executeScript({ target: { tabId: t }, files: ["active-tab-script.js"] }) } catch {} Sr(e.url?.includes("linkedin.com") ?? !1)}))}))The code that does this
The active-tab script returns page text, title, and URL
chrome.runtime.onMessage.addListener((function(t, e, n) { return "getPageContent" === t && (A({ category: "chrome-extension", message: `getPageContent from ${window.location.href}`, level: "info" }), window.location.href.includes("docs.google.com/document") ? (A({ category: "chrome-extension", message: "getPageContent from Google Doc", level: "info" }), chrome.runtime.sendMessage("getAuthToken", (function(t) { if (t) { const e = new RegExp(/https:\/\/docs.google.com\/document\/d\/(.*)\//).exec(window.location.href), s = e?.[1]; if (s) { const e = { method: "GET", headers: { Authorization: `Bearer ${t}`, "Content-Type": "application/json" } }; try { fetch(`https://docs.googleapis.com/v1/documents/${s}`, e).then((t => t.json())).then((function(t) { const e = t.body?.content?.map((t => t.paragraph?.elements)).flat().filter((t => Boolean(t))).map((t => t?.textRun)), s = e?.map((t => t?.content)).join("") ?? ""; n({ source: "Google Docs", text: s, title: t.title, url: window.location.href }) })) } catch (t) { j(`Fetch failed for for https://docs.googleapis.com/v1/documents/${s}`) } } else n({ source: "Google Docs", text: "Unable to get the content of this document", title: document.title, url: window.location.href }), j(`No documentId found for ${window.location.href}`) } else n({ source: "Google Docs", text: "Unable to get the content of this document", title: document.title, url: window.location.href }), j(`No auth token found for ${window.location.href}`) }))) : window.location.href.includes("docs.google.com/spreadsheets") ? (A({ category: "chrome-extension", message: "getPageContent from Google Sheet", level: "info" }), chrome.runtime.sendMessage("getAuthToken", (function(t) { if (t) { const e = new RegExp(/https:\/\/docs.google.com\/spreadsheets\/d\/(.*)\/edit\?gid=(.*)#/).exec(window.location.href), s = e?.[1], o = e?.[2]; if (s) { const e = { method: "GET", headers: { Authorization: `Bearer ${t}`, "Content-Type": "application/json" } }; try { fetch(`https://sheets.googleapis.com/v4/spreadsheets/${s}?includeGridData=true`, e).then((t => t.json())).then((function(t) { const e = t.sheets?.find((t => t.properties?.sheetId === Number(o))), s = e?.data?.map((t => t.rowData?.map((t => t.values?.map((t => t.formattedValue)))))).flat(1); n({ source: "Google Sheets", text: `This text represents the values in the rows of a spreadsheet: ${JSON.stringify(s)}`, title: t.properties?.title ?? document.title, url: window.location.href }) })) } catch (t) { j(`Fetch failed for for https://sheets.googleapis.com/v4/spreadsheets/${s}`) } } else n({ source: "Google Sheets", text: "Unable to get the content of this spreadsheet", title: document.title, url: window.location.href }), j(`No spreadsheetId found for ${window.location.href}`) } else n({ source: "Google Sheets", text: "Unable to get the content of this spreadsheet", title: document.title, url: window.location.href }), j(`No auth token found for ${window.location.href}`) }))) : window.location.href.includes("linkedin.com") ? (A({ category: "chrome-extension", message: "getPageContent from LinkedIn", level: "info" }), n({})) : (A({ category: "chrome-extension", message: "getPageContent from standard webpage", level: "info" }), n({ text: document.documentElement.innerText, title: document.title, url: window.location.href }))), !0}))The code that does this
The side panel embeds the remote Zapier Agents page
<html><body><head><style>html, body { margin: 0; padding: 0; height: 100%; } iframe { position: fixed; inset: 0; width: 100%; height: 100%; border: 0; }</style><script defer="defer" src="sidepanel.js"></script></head><iframe src="https://agents.zapier.com/chrome-extension" id="central" allow="clipboard-write"></iframe></body></html>Remote services named in the active-tab content path
- agents.zapier.com
Zapier Agents iframe and page context that receives browser-context responses.
- docs.googleapis.com
Google Docs API endpoint queried when the active tab is a Google Doc and an OAuth token is available.
- sheets.googleapis.com
Google Sheets API endpoint queried when the active tab is a Google Sheet and an OAuth token is available.
Visible tab screenshots relayed to Zapier Agents on request
The extension can capture the visible browser tab as a JPEG when its Zapier Agents page requests a screenshot.
The image is relayed to agents.zapier.com and can include sensitive content visible on the page.
What actually happens
A logged-in Zapier Agents side panel requests a browser screenshot.
The extension captures the visible tab as a JPEG and relays the screenshot response to Zapier Agents.
Captured request
Fields in the request
- Visible tab informationScreenshot of the active tab (illustrative)
The request can include what is currently visible in your active browser tab, including page content shown on screen.
Observation
Dynamic analysis confirmed the screenshot capture path in the extension code. Earlier testing could not trigger the behavior without Zapier authentication and an open side panel.