FrankenPHP, Unicode Path Traversal to RCE, GHSA-v4h7-cj44-8fc8 (High)

Listen to this Post

How the mentioned CVE works (around 20 lines):

The vulnerability resides in `splitPos()` within cgi.go. Two flaws arise when a request path contains non-ASCII bytes. Flaw 1 – stale match: In the inner loop, if a byte ≥ `utf8.RuneSelf` and `splitSearchNonASCII.IndexString()` returns -1, the loop breaks without setting match = false. The outer code then returns `i+splitLen` while `match` remains true, treating a non-.php file (e.g., name.<U+00A1>.txt) as PHP. Flaw 2 – Unicode equivalence: `search.New(language.Und, search.IgnoreCase)` performs aggressive Unicode folding, mapping many lookalike characters (﹒, ., p, ⓟ, 𝗽, 𝓅, etc.) onto ASCII ., p, h, p. Thus a path containing `shell﹒php` or `shell.ⓟⓗⓟ` is matched as .php. Both flaws stem from using a Unicode-aware case‑insensitive search on an ASCII‑only, lower‑cased split entry, ignoring that any byte ≥ `utf8.RuneSelf` cannot legitimately match. An attacker who can upload a file with a crafted name (e.g., `poc.%C2%A1.txt` or shell.%F0%9D%97%BD.php) and then request it with a manipulated URL achieves RCE because FrankenPHP sets `SCRIPT_FILENAME` to that non‑PHP file and PHP executes it.

dailycve form:

Platform: FrankenPHP
Version: Before fix
Vulnerability : Unicode path bypass
Severity: High (8.1)
date: 2026-05-15

Prediction: Patch expected 2026-05-30

What Undercode Say:

Reproduce flaw 1 (stale match)
curl -i --path-as-is "http://target/poc-match-unset.%C2%A1.txt/trigger"
Reproduce flaw 2 (Unicode equivalence)
curl -i --path-as-is "http://target/shell.%F0%9D%97%BD%F0%9D%97%B5%F0%9D%97%BD.anything/trigger"
Check splitPos() behavior standalone
go run poc.go

Exploit:

Upload a file named `shell.ⓟⓗⓟ` (or any Unicode lookalike) containing PHP code. Send `GET /shell.%E2%93%9F%E2%93%97%E2%93%9F/anything` – FrankenPHP misinterprets it as `.php` and executes the uploaded code. Also works with non-ASCII bytes like `¡` in file.¡.txt.

Protection from this CVE:

Patch FrankenPHP to remove `golang.org/x/text/search` fallback entirely. Replace with a tight byte loop that treats any byte ≥ `utf8.RuneSelf` as immediate non‑match. Validate all split entries are ASCII and lower‑cased (already guaranteed). Alternatively, deny requests containing non‑ASCII bytes in the path if strict ASCII enforcement is acceptable.

Impact:

Remote Code Execution (RCE) with CVSS 8.1 (High). Attacker needs ability to place a file with a crafted name on the server (e.g., via upload, storage write). Then a single unauthenticated HTTP request with a crafted path executes arbitrary PHP code in the FrankenPHP process, leading to full system compromise.

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

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