A AegiFlow
HIGHCVSS 8.7EPSS 0.5%

CVE-2026-57584

Phalcon: Catastrophic backtracking (ReDoS) in the default Phalcon Router route lead to remote unauthenticated DoS

Published
2026-08-28
Modified
2026-08-28
EPSS percentile
42%
Aliases
GHSA-x7rj-f32v-7jjg
Sources
github-advisory

Summary

## Summary Every Phalcon MVC application built with a default router (`new Phalcon\Mvc\Router()` or `new Phalcon\Mvc\Router(true)`, which is the normal case) registers a built-in route whose compiled PCRE pattern is `#^/([\w0-9\_\-]+)/([\w0-9\.\_]+)(/.*)*$#u`. The trailing `(/.*)*` is a nested quantifier whose group body (`/.*`) overlaps itself (`.` matches `/`, and there is no `s`/DOTALL flag), so when the final `$` is forced to fail the engine explores roughly `2^(N/2)` ways to split a run of `N` slashes, causing classic catastrophic backtracking. `Phalcon\Mvc\Router::handle()` runs on **every** request and matches this pattern against the attacker-controlled request URI, so a single short request can burn seconds-to-minutes of CPU per request. The same `(/.*)*` construct is also produced by the `/:params` placeholder (`Phalcon\Mvc\Router\Route::compilePattern()`) and by the CLI router (`Phalcon\Cli\Router` / `Phalcon\Cli\Router\Route`). ## Details The vulnerable pattern is emitted in four places, all carrying the same `*` nested quantifier: - Default MVC route registration `phalcon/Mvc/Router.zep` (`Router::__construct()`): `"#^/([\\w0-9\\_\\-]+)/([\\w0-9\\.\\_]+)(/.*)*$#u"`, with paths `["controller": 1, "action": 2, "params": 3]`. - `/:params` placeholder expansions `phalcon/Mvc/Router/Route.zep` (`Route::compilePattern()`): `str_replace("/:params", "(/.*)*", pattern)`. - Default CLI route `phalcon/Cli/Router.zep` (`Router::__construct()`): `"#^(?::delimiter)?([a-zA-Z0-9\\_\\-]+):delimiter([a-zA-Z0-9\\.\\_]+)(:delimiter.*)*$#"`. - CLI `/:params` expansion `phalcon/Cli/Router/Route.zep` (`Route::compilePattern()`): `"(" . this->delimiter . ".*)*"`. `Router::handle()` matches the request URI against this pattern on every request (the combined-regex fast path and the per-route dynamic loop both call `preg_match()` with it). When the subject string ends in a byte that the group cannot consume (for example a newline, since `.` does not match `\n`), the anchored `$` cannot be satisfied and the engine backtracks over every partition of the leading run of slashes, which is exponential in the number of slashes. ## Remote reachability In the default MVC configuration the router uses `URI_SOURCE_GET_URL`, i.e. it reads the request path from `$_GET["_url"]`, which the web server populates from the rewritten request path. **PHP URL-decodes `$_GET`**, so a request path containing `%0a%0a` arrives as the literal two-byte string `"\n\n"`. The two newlines are the trigger: `.` cannot match `\n`, and PCRE's `$` forgives exactly one trailing `\n`, so two of them force the match to fail and unleash the backtracking. No authentication, cookies, or application-specific routes are needed. Example malicious request path (≈40 bytes): `/a/a////////////////////////////////%0a%0a` (two short segments, a run of `/`, then `%0a%0a`). Applications configured with `URI_SOURCE_SERVER_REQUEST_URI` are not reachable through this specific newline trick because `REQUEST_URI` is not URL-decoded; they remain exposed to the underlying CPU amplification when the unmatchable tail can be introduced by other means. ## Proof of Concept ```php setDI($di); echo "phalcon : " . phpversion("phalcon") . "\n"; echo "pcre.backtrack_limit: " . ini_get("pcre.backtrack_limit") . "\n"; echo "pcre.jit : " . ini_get("pcre.jit") . "\n"; // Default configuration foreach ($router->getRoutes() as $r) { if (strpos($r->getCompiledPattern(), "(/.*)*") !== false) { echo "vulnerable route : " . $r->getCompiledPattern() . "\n"; } } echo "\n"; function bench(Router $router, string $uri, string $label): void { $t0 = hrtime(true); try { $router->handle($uri); } catch (\Throwable $e) { // matching failure and fallback to time } $ms = (hrtim

Affected packages

EcosystemPackageAffected versionsFixed versions
Packagistphalcon/cphalcon5.15.0

Remediation: Upgrade to 5.15.0 or later.

References

Includes data from the GitHub Advisory Database, licensed under CC-BY 4.0.

CVE® is a registered trademark of The MITRE Corporation. CVE content reproduced under the CVE Terms of Use; copyright designation © MITRE.

EPSS scores provided by the FIRST.org Exploit Prediction Scoring System.