Skip to content

CVE-2025-71334: Verified Reproduction

CVE-2025-71334: Flowise arbitrary file access via unvalidated chatflowId/chatId

CVE-2025-71334 is verified against FlowiseAI/Flowise · npm. Affected versions: GitHub Advisory Database and OSV list flowise >=2.2.8 and <3.0.6; patched version is 3.0.6. Vulnerability class: Path Traversal. This critical reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00310.

REPRO-2026-00310 FlowiseAI/Flowise · npm Path Traversal Jul 28, 2026 CVE entry ↗ .txt
Severity
CRITICAL
Confidence
HIGH
Reproduced in
66m 57s
Tool calls
382
Spend
$20.14
01 · Overview

What Is CVE-2025-71334?

CVE-2025-71334 is a critical-severity Path Traversal vulnerability affecting FlowiseAI/Flowise GitHub Advisory Database and OSV list flowise >=2.2.8 and <3.0.6; patched version is 3.0.6.. Pruva has independently reproduced it and publishes a verified, runnable proof-of-concept (reproduction REPRO-2026-00310).

02 · Severity & CVSS

CVE-2025-71334 Severity

CVE-2025-71334 is rated critical severity.

CRITICAL threat level
Weakness CWE-73

Critical — the most severe class — typically remotely exploitable with severe impact. Treat as an emergency.

03 · Affected Versions

Affected FlowiseAI/Flowise Versions

FlowiseAI/Flowise · npm versions GitHub Advisory Database and OSV list flowise >=2.2.8 and <3.0.6; patched version is 3.0.6. are affected.

How to Reproduce CVE-2025-71334

$ pruva-verify REPRO-2026-00310
or curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00310/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh
Run in a VM or disposable container. This exploits a real vulnerability.
06 · Proof of Reproduction

Proof of Reproduction for CVE-2025-71334

Information disclosure — reproduced
  • reached the target end-to-end
  • full exploit chain demonstrated
  • on the real production code path
  • high confidence
  • the upstream fix blocks the same trigger
Trigger

Unauthenticated GET query parameters chatflowId=<valid UUID>, chatId=../.., and fileName=outside-secret.txt

Attack chain
  1. GET /api/v1/get-upload-file
  2. get-upload-file controller
  3. streamStorageFile local fallback path
Runnable proof: reproduction_steps.sh
Captured evidence: fixed attempt1 servicefixed attempt2 service
How the agent worked 696 events · 382 tool calls · 1h 7m
1h 7mDuration
382Tool calls
79Reasoning steps
696Events
43Dead-ends
Agent activity over 1h 7m
Policy
1
Support
46
Repro
347
Judge
35
Variant
262
Verify
1
0:0066:46

Root Cause and Exploit Chain for CVE-2025-71334

Versions: package/component: flowise / flowise-components, specifically the public get-upload-file handler and streamStorageFile local-storage fallback.Fixed: version tested: Flowise 3.0.6 (source commit 89a0f23fe5e9c0b1ee85ee1175032c6b9e5ac9c1; exact official linux/amd64 image manifest sha256:86b83c5f55cd7989453789a39c568d08885be50e74faf9abd5e238269bcfe489).

Flowise 3.0.5 exposes the public GET /api/v1/get-upload-file endpoint without authentication and passes its attacker-controlled chatId query parameter into the local-storage path built by streamStorageFile. The function validates chatflowId but not chatId. In its legacy no-organization fallback, path.join(storageRoot, chatflowId, chatId, filename) therefore normalizes ../ segments and can resolve outside the configured storage root. A remote unauthenticated request can consequently retrieve a file from the parent of local storage. This run reproduced the issue twice against real Flowise 3.0.5 HTTP servers and showed that the identical requests are rejected twice by Flowise 3.0.6.

  • Affected package/component: flowise / flowise-components, specifically the public get-upload-file handler and streamStorageFile local-storage fallback.
  • Affected version reproduced: Flowise 3.0.5 (source commit ba6a602cbe87d9f55c9ee6aebb6407ec2f2066b5; exact official linux/amd64 image manifest sha256:30d4fdf8b9e215abff31a67ab104a9750ca25354fe98fe97a3481bbca0352098). The ticket describes Flowise versions before 3.0.6 as affected.
  • Fixed version tested: Flowise 3.0.6 (source commit 89a0f23fe5e9c0b1ee85ee1175032c6b9e5ac9c1; exact official linux/amd64 image manifest sha256:86b83c5f55cd7989453789a39c568d08885be50e74faf9abd5e238269bcfe489).
  • Risk: High/critical confidentiality risk. An unauthenticated network client with a valid chatflow UUID can read files reachable through traversal from the configured local storage hierarchy. In the default layout, this can expose application state such as the SQLite database and its sensitive records. The vulnerable fallback also copies the source into storage and unlinks the original, creating a data-tampering/availability side effect.

Impact Parity

  • Disclosed/claimed maximum impact: Pre-auth arbitrary file read/write, information disclosure, and data tampering through Flowise file-storage APIs.
  • Reproduced impact: Pre-auth arbitrary file read through the real HTTP endpoint. A unique secret was created outside BLOB_STORAGE_PATH; an HTTP request sent without cookies, Authorization, API key, or x-request-from returned that exact secret with status 200. The vulnerable fallback then moved the source file into storage, also demonstrating an unauthorized filesystem mutation.
  • Parity: full for the canonical contract's info_leak impact and the unauthenticated API surface.
  • Not demonstrated: A general attacker-controlled arbitrary-file-write primitive was not needed for the canonical claim and was not claimed as independently proven here. Code execution was neither required nor attempted.

Root Cause

The endpoint is included in WHITELIST_URLS, so Flowise's global API middleware allows requests to /api/v1/get-upload-file without authentication. The controller reads chatflowId, chatId, and fileName directly from query parameters, resolves the organization from the referenced chatflow, and calls:

streamStorageFile(chatflowId, chatId, fileName, orgId)

In Flowise 3.0.5, streamStorageFile validates that chatflowId is a UUID and rejects traversal only in chatflowId. It does not apply isPathTraversal to chatId. The primary local path is checked, but when it does not exist the migration fallback constructs a second path without the organization prefix:

const fallbackPath = path.join(getStoragePath(), chatflowId, chatId, sanitizedFilename)

Because Node's path.join normalizes traversal segments, a value such as chatId=../.. transforms storageRoot/<chatflow UUID>/../../outside-secret.txt into a path above storageRoot. Critically, this fallback path is not checked with the primary path's absolute/root-containment checks before existsSync, copyFileSync, unlinkSync, and createReadStream are used. Filename sanitization cannot constrain traversal supplied through the separate chatId component.

Flowise 3.0.6 fixes the reproduced mechanism by extending the early guard to both path components:

if (isPathTraversal(chatflowId) || isPathTraversal(chatId)) {
    throw new Error('Invalid path characters detected in chatflowId or chatId')
}

The version-paired source diff is captured in bundle/repro/root_cause_source.txt. The release change is present between commits ba6a602cbe87d9f55c9ee6aebb6407ec2f2066b5 and 89a0f23fe5e9c0b1ee85ee1175032c6b9e5ac9c1.

Reproduction Steps

  1. Run bundle/repro/reproduction_steps.sh from any directory. It honors PRUVA_ROOT and the prepared project cache described by bundle/project_cache_context.json.

  2. The script verifies the exact Flowise Git tags/commits and the presence/absence of the fixing hunk. It then downloads and digest-pins the official linux/amd64 Flowise 3.0.5 and 3.0.6 container filesystems, and runs their bundled Node runtimes and real Flowise CLI/server binaries directly.

  3. For each of two isolated attempts per version, it starts Flowise with SQLite and local storage, waits for /api/v1/ping, performs administrative setup to create a valid chatflow, places a unique secret just outside BLOB_STORAGE_PATH, and sends the exploit request with no authentication material:

    GET /api/v1/get-upload-file?chatflowId=<valid UUID>&chatId=../..&fileName=outside-secret.txt
    
  4. Expected evidence:

    • Both 3.0.5 attempts return HTTP 200 and the exact unique outside secret, followed by VULNERABLE_UNAUTHENTICATED_READ_CONFIRMED.
    • Both 3.0.6 attempts return HTTP 500 with Invalid path characters detected in chatflowId or chatId; the source file remains unchanged, followed by FIXED_REJECTION_CONFIRMED.
    • The script exits 0 only after all four checks pass and prints REPRODUCTION_CONFIRMED.

Evidence

  • bundle/logs/reproduction_steps.log — complete image acquisition, server startup, request/response, and four-attempt verdict transcript.
  • bundle/logs/vulnerable_attempt1_response.txt and bundle/logs/vulnerable_attempt2_response.txt — unique bytes disclosed by the unauthenticated endpoint.
  • bundle/logs/fixed_attempt1_response.txt and bundle/logs/fixed_attempt2_response.txt — fixed-build rejection JSON.
  • bundle/logs/vulnerable_attempt1_service.log, bundle/logs/vulnerable_attempt2_service.log, bundle/logs/fixed_attempt1_service.log, and bundle/logs/fixed_attempt2_service.log — real Flowise initialization and listening-server evidence.
  • bundle/logs/flowise_3.0.5_image_manifest.json and bundle/logs/flowise_3.0.6_image_manifest.json — exact official linux/amd64 OCI manifest and layer identities.
  • bundle/repro/source_identity.log — source tags, commits, and image digests.
  • bundle/repro/runtime_manifest.json — strict runtime manifest with entrypoint_kind=endpoint and service, healthcheck, and target-path flags set to true.
  • bundle/repro/root_cause_source.txt — bounded vulnerable code, fixed diff, whitelist, and controller source evidence.

Representative successful-run excerpts:

unauthenticated_status=200
PRUVA_VULNERABLE_1_<run token>
VULNERABLE_UNAUTHENTICATED_READ_CONFIRMED
unauthenticated_status=500
{"statusCode":500,"success":false,"message":"Invalid path characters detected in chatflowId or chatId","stack":{}}
FIXED_REJECTION_CONFIRMED

Recommendations / Next Steps

  • Upgrade self-managed Flowise installations to 3.0.6 or later.
  • Validate every attacker-controlled path segment (chatflowId, chatId, organization identifiers, and filenames) before storage-provider use. Prefer strict expected-format validation, such as UUID validation where applicable.
  • After constructing both primary and fallback paths, resolve them with path.resolve and enforce containment using a separator-aware relative-path check; a simple string prefix is insufficient.
  • Remove or tightly constrain legacy fallback/migration behavior on unauthenticated routes. Filesystem moves should not occur as a side effect of a public download request.
  • Add integration tests over the real unauthenticated HTTP boundary for encoded and unencoded traversal forms, both download endpoints, all storage providers, and fixed-version fail-closed behavior.
  • Return a client error (for example HTTP 400) rather than HTTP 500 for invalid path input to reduce unnecessary internal-error behavior.

Additional Notes

  • Idempotency: The final script performs two isolated vulnerable and two isolated fixed attempts in one run, and it is being executed twice consecutively. Per-attempt directories, databases, accounts, chatflows, ports, and secrets are recreated; each run uses a new random token.
  • Authentication boundary: Registration/login and chatflow creation are setup actions only. The exploit request itself is emitted by a fresh curl invocation without a cookie jar or any authentication-related header.
  • Execution mode: No sanitizer, direct parser harness, mock server, or reimplemented storage function is used. The script invokes the real released Flowise CLI and HTTP server from digest-pinned official product images.
  • Operational detail: The official image filesystems are streamed and extracted rather than imported into the rootless Docker daemon because that daemon's private layer store was too small for these multi-gigabyte images. This does not change product bytes or runtime behavior: each image's own bundled musl loader, Node executable, Flowise package, dependencies, and CLI are executed.
  • Known precondition: The read handler requires a valid chatflow UUID. The script creates one through the normal authenticated product API before testing the separate public download boundary.

CVE-2025-71334 Reproduction Transcript

The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.

Full session Replay every step — scrub the timeline or play it back.

Event 1/40
0:002:54
0:00
session startedgpt-5.6-sol · CVE-2025-71334 · REPRO-20
0:05
0:06
web search
0:19
0:20
web search
0:22
web search
0:25
0:43
web search
0:44
web search
0:45
0:46
web search
0:50
1:07
1:07
1:07
1:08
web search
1:09
web search
1:10
1:26
1:26
1:34
1:37
1:41
2:06
2:10
2:13
2:15
2:16
2:23
2:52
2:54
web search
2:54
08 · How to Fix

How to Fix CVE-2025-71334

Coming soon

Step-by-step mitigation and hardening guidance for CVE-2025-71334 — configuration checks, workarounds where no patch exists, and how to verify you're protected — is on the way.

10 · FAQ

FAQ: CVE-2025-71334

Is CVE-2025-71334 exploitable?

Yes. Pruva independently reproduced CVE-2025-71334 in FlowiseAI/Flowise and verified the exploit fires end-to-end in a sandboxed environment. A runnable proof-of-concept script and the full agent transcript are on this page (reproduction REPRO-2026-00310).

How severe is CVE-2025-71334?

CVE-2025-71334 is rated critical severity.

What type of vulnerability is CVE-2025-71334?

CVE-2025-71334 is classified as CWE-73, a Path Traversal vulnerability.

Which versions of FlowiseAI/Flowise are affected by CVE-2025-71334?

FlowiseAI/Flowise GitHub Advisory Database and OSV list flowise >=2.2.8 and <3.0.6; patched version is 3.0.6. is affected by CVE-2025-71334.

How can I reproduce CVE-2025-71334?

Pruva provides a verified reproduction script on this page. Download it and run it inside an isolated environment such as a container or virtual machine — never against production. The reproduction was confirmed end-to-end by Pruva's automated agents.

Is the CVE-2025-71334 reproduction verified?

Yes. Pruva reproduced CVE-2025-71334 with high confidence in a sandboxed environment, capturing the full agent transcript and artifacts as evidence.
11 · References

References for CVE-2025-71334

Authoritative sources for CVE-2025-71334 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.