Is Genspark safe?
Genspark AI Agent opens a persistent WebSocket to genspark.ai and executes server-sent commands to capture screenshots, read page content, inject input, and monitor network traffic on any open tab.
On startup, the extension registers a unique browser ID with genspark.ai and maintains a persistent WebSocket connection. Through this channel, the genspark.ai server can remotely invoke browser automation tools — including taking screenshots, reading full page text and accessibility trees, injecting mouse and keyboard events, filling form fields, navigating tabs, and capturing all HTTP network traffic — on any tab in the user's browser. Results from each operation are sent back to genspark.ai's servers over the same connection.
Who publishes itGenspark Inc. - no other listings under this identity, 2 shared hostnames
Genspark Inc. - no other listings under this identity, 2 shared hostnames
What this publisher told the store about itself, and the other listings that told it the same thing.
Shared hosts - 2 hostnames
Hostnames hardcoded in this extension that few other listings call. That can mean one operator behind both, and it can equally mean a small shared vendor, so it is context rather than a conclusion. Hosts that many listings call are left out: they are services, not connections.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Persistent server-controlled RPC channel registered on every browser start
Every Chrome start with this installed, it generates or reuses a device ID, registers with genspark.ai, opens a long-lived WebSocket.
Over it, genspark.ai can send RPC commands: screenshots, page reads, clicks, form fills, capture.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-200
- Source
- Dynamic sandbox
You install the Genspark extension and start Chrome.
No further interaction is needed, registration fires automatically at service-worker startup.
The extension registers a permanent device ID with genspark.ai and opens a persistent WebSocket that lets genspark.ai send browser-automation commands to your Chrome.
The channel is re-established every 3 seconds after any disconnect and survives browser restarts via a stored identifier.
Server returns {data:{id:"<connection_id>"}}; extension then opens wss://www.genspark.ai/browser_extension_connect/connect?browser_connection_id=<connection_id>
- Content-Type
- application/json
{ "browser_id": "browser_1779111700207_dv4ppn1ezw"}Ties every future registration to the same browser install. Made once, reused across restarts, giving genspark.ai a persistent handle.
- Location
- chrome.storage.local key 'browser_extension_id'
browser_1779111700207_dv4ppn1ezwRegistration and WebSocket connect (background.js:4288-4358)
// Constantsconst STORAGE_KEY = 'browser_extension_id';const HEARTBEAT_TIMEOUT_MS = 15000;// Singleton connection managerconst connectionManager = new class { constructor() { this.browserId = null; this.connectionId = null; this.ws = null; this.heartbeatTimer = null; this.reconnectTimer = null; this.isManualDisconnect = false; this.lastPingTime = 0; } async init() { try { await this.ensureBrowserId(); await this.registerAndConnect(); } catch (err) { console.error('Failed to initialize browser extension connection:', err); this.scheduleReconnect(); // retry in 3s } } async ensureBrowserId() { const stored = await chrome.storage.local.get(STORAGE_KEY); if (stored[STORAGE_KEY]) { this.browserId = stored[STORAGE_KEY]; // reuse existing ID } else { this.browserId = this.generateBrowserId(); // create new permanent ID await chrome.storage.local.set({ [STORAGE_KEY]: this.browserId }); } } generateBrowserId() { // format: browser_{timestamp}_{random} return `browser_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`; } async registerAndConnect() { const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), 5000); let response; try { response = await fetch(`${BASE_URL}/api/register_browser_extension`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ browser_id: this.browserId }), signal: controller.signal }); } finally { clearTimeout(timeout); } if (!response.ok) throw new Error(`Registration failed with status: ${response.status}`); const { data } = await response.json(); this.connectionId = data.id; await this.connectWebSocket(); }};RPC dispatcher, tools executed on server command (background.js:4175-4194)
// Called for every incoming WebSocket 'request' messageasync function handleRpcRequest(message, sendMessage) { const { id, method, params = {} } = message; let result, error = null; try { // Use tabId from params or fall back to the currently active tab const tabId = params.tabId || await getActiveTabId(); if (tabId) globalContext.tabId = tabId; // Dispatch to the registered tool (screenshot, click, form_input, navigate, ...) result = await toolRegistry.executeTool(method, params, globalContext); // ... } // Registered tools include: computer (screenshot/click/keypress/drag), // browser_control_accessibility_tree, browser_control_network_capture, // browser_control_tabs_context, browser_control_form_input, // browser_control_navigate, browser_control_download_status, and more.}- www.genspark.ai
Registration endpoint (/api/register_browser_extension) issues the connection_id; the WebSocket endpoint carries RPC commands. Both run by Genspark AI.
Where it sends data
Destinations our analysis observed Genspark 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.
- www.genspark.ai
Genspark sends data to www.genspark.ai. No other extension we have analysed sends data here.