BUG_Author: Zy0t1

Affected Version: flow-ci / flow-core-x all versions (since 2019 to master branch, never patched)

Vendor: FlowCI/flow-core-x

Software: flow-ci

Vulnerability Files: - store/src/main/java/com/flowci/store/LocalFileManager.java (L56, L67, L75, L87, L94 — 5 sinks in exist, save, read, remove methods)

CWE: CWE-22 - Improper Limitation of a Pathname to a Restricted Directory ("Path Traversal") - The software uses external input to construct a pathname that is intended to identify a file or directory located beneath a restricted parent directory, but it does not properly neutralize special elements such as ../ sequences that can resolve to a location that is outside of that directory.

CVSS 3.1: 7.5 (High) - AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H

Description:

flow-ci's LocalFileManager implementation constructs file paths with Paths.get(dir.toString(), fileName) and passes them directly to filesystem operations. The fileName parameter is not sanitized: there is no detection of .., no normalize() call, and no startsWith(base) boundary check. Java's Paths.get(a, b) preserves .. path components, so a filename such as ../../../../cve02_browser_escape.txt can escape the intended storage directory when the operating system resolves the path.

Five vulnerable sinks exist:

  1. exist() — L56: Paths.get(dir.toString(), fileName) — traversal-aware existence check.
  2. save() — L67: Paths.get(dir.toString(), fileName) — arbitrary file write.
  3. read() — L75: Paths.get(dir.toString(), fileName) — arbitrary file read.
  4. remove(fileName, ...) — L87: Paths.get(dir.toString(), fileName) — arbitrary file delete.
  5. remove(filePath) — L94: Paths.get(filePath) — deletes a fully attacker-controlled path.

Several HTTP entry points pass user-controlled names to the storage layer: