Is AutoBanana for Google Gemini™ - Automatic Batch Creator safe?
AutoBanana for Google Gemini™ - Automatic Batch Creator is high risk. Clicking the toolbar Send button on a supported Google AI page submits your prompt and posts a Google Analytics event, send_button_clicked, including the prompt text, a browser client ID, and a session ID from the content-script…
Who publishes itAutojourney - 4 other listings from the same operator, 2 of them carrying a finding
Autojourney - 4 other listings from the same operator, 2 of them carrying a finding
What this publisher told the store about itself, and the other listings that told it the same thing.
Same store account
4 other listings published from this account, 26k+ users between them. 2 of them carry a finding.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Submitted AI prompts are sent to Google Analytics
Clicking the toolbar Send button on a supported Google AI page submits your prompt and posts a Google Analytics event, send_button_clicked, including the prompt text, a browser client ID, and a session ID from the content-script bridge.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-359
- Source
- Dynamic sandbox
You click the extension toolbar Send button after writing a prompt.
This occurs on manifest-scoped Google AI pages such as gemini.google.com, aistudio.google.com, and labs.google.
The extension submits the prompt and sends a matching analytics event.
The send_button_clicked event includes the current prompt text read from the extension UI.
- Submitted prompt textGenerate three launch-banner ideas for Acme's July campaign (illustrative)
The text you entered can include sensitive ideas, work content, or personal details from the AI request.
- Browser client ID9f544db0-3a58-4b89-badc-705252f7a4dd (illustrative)
This lets analytics events from the same browser be linked together over time.
- Session ID1720877144468 (illustrative)
This groups events from the same browsing session so one Send click can be tied to nearby extension activity.
- Event name and UI contextsend_button_clicked; tab=midjourney (illustrative)
This records that the event came from clicking the toolbar Send button and can include which tab or mode was active.
The Send button passes prompt text into the analytics sender
Readable equivalent of Ft()
scripts/main.jsconst GA_ENDPOINT = "https://www.google-analytics.com/mp/collect";const MEASUREMENT_ID = "G-2VLF2SK5P2";const API_SECRET = "<redacted>";const FALLBACK_CLIENT_ID = Date.now().toString();const FALLBACK_SESSION_ID = Date.now().toString();const ENGAGEMENT_TIME_MS = 100;async function getClientId() { try { return Xse ? FALLBACK_CLIENT_ID : (await km("getGAClientId", "content", {})).clientId; } catch { return FALLBACK_CLIENT_ID; }}async function getSessionId() { try { return Xse ? FALLBACK_SESSION_ID : (await km("getGASessionId", "content", {})).sessionId; } catch { return FALLBACK_SESSION_ID; }}async function sendAnalyticsEvent(eventName, params) { const clientId = await getClientId(); const sessionId = await getSessionId(); const email = Ys(); const isMember = OYe(); return fetch(`${GA_ENDPOINT}?measurement_id=${MEASUREMENT_ID}&api_secret=${API_SECRET}`, { method: "POST", body: JSON.stringify({ client_id: clientId, events: [{ name: eventName, params: { ...params, session_id: sessionId, engagement_time_msec: ENGAGEMENT_TIME_MS, discord_user_email: email, is_autojourney_member: isMember } }] }) });}Readable equivalent of the Send click path
scripts/main.jsfunction readPromptText() { return F(z).trim();}const fallbackSendButton = jsx("div", { title: Re(H.footer.send), id: "J_auto_midjourney_send", className: ye({ "auto-midjourney-send": true, "auto-midjourney-hidden": V }), onClick: () => { ir(); Ft("send_button_clicked", { tab: t, prompt: readPromptText() }); Ft("send_prompt", { by: "footer_send", repeat: S }); }});const primarySendButton = jsx(ln, { type: "primary", id: "J_auto_midjourney_send", onClick: () => { ir(); Ft("send_button_clicked", { tab: t, prompt: readPromptText() }); Ft("send_prompt", { by: "footer_send", repeat: S }); }, children: Re(H.footer.send)});Readable equivalent of the ID bridge
scripts/content.jsasync function getOrCreateClientId() { let clientId = (await chrome.storage.local.get("clientId")).clientId; if (!clientId) { clientId = self.crypto.randomUUID(); await chrome.storage.local.set({ clientId }); } return clientId;}async function getOrCreateSessionId() { let { sessionData } = await chrome.storage.session.get("sessionData"); const now = Date.now(); if (sessionData && sessionData.timestamp) { if ((now - sessionData.timestamp) / 60000 > R) { sessionData = null; } else { sessionData.timestamp = now; await chrome.storage.session.set({ sessionData }); } } if (!sessionData) { sessionData = { session_id: now.toString(), timestamp: now.toString() }; await chrome.storage.session.set({ sessionData }); } return sessionData.session_id;}function startBridge() { window.addEventListener("message", async event => { const message = event.data; if (message?.source !== n || message?.to !== "content") return; if (message.type === "getGAClientId") { window.postMessage({ source: n, to: "page", from: "content", type: `${message.type}:${message.id}`, clientId: await getOrCreateClientId() }, "*"); } else if (message.type === "getGASessionId") { window.postMessage({ source: n, to: "page", from: "content", type: `${message.type}:${message.id}`, sessionId: await getOrCreateSessionId() }, "*"); } });}- www.google-analytics.com
Receives the Measurement Protocol POST containing the send_button_clicked event, prompt text, client_id, and session_id.