RouterFactory in its service provider but has no site router class (<Namespace>\Site\Service\Router). Real-world examples: Akeeba Backup 10.0.0 (com_akeebabackup) and Regular Labs ReReplacer (com_rereplacer), which are backend-only.GET https://example.com/?option=com_akeebabackup&view=json&json=xThe request is answered with 301 Location: https://example.com/ and this warning is logged:
PHP Warning: Uninitialized string offset 0 in .../libraries/vendor/joomla/application/src/AbstractWebApplication.php on line 418
In our case the trigger was an external monitoring tool probing Akeeba's legacy JSON API URL, but any visitor can trigger it with a crafted URL.
6.2
When the SEF URL can't be built, enforceSEF() should leave the request alone: no redirect, and the component (or a 404) handles it as it would with strict routing off.
A 301 redirect to the site root, plus a PHP warning in the error log on every such request.
Call chain:
Sef::onAfterRoute() → enforceSEF() (plugins/system/sef/src/Extension/Sef.php, line 164).$newRoute = Route::_($parsedVars, false); (line 542).SiteRouter::buildComponentPreprocess() → getComponentRouter() → bootComponent()->createRouter() → RouterFactory::createRouter() throws RuntimeException('No router available for this application.') because the site router class doesn't exist (libraries/src/Component/Router/RouterFactory.php, line 86).Route::_() catches the RuntimeException and returns null (libraries/src/Router/Route.php, lines 100-105, the B/C behaviour deprecated since 3.9).enforceSEF(): new Uri(null) has no query and $route !== null, so it calls $app->redirect(null, 301) (line 546).AbstractWebApplication::redirect(), preg_split() turns null into '', $url[0] raises the warning (line 418), and the empty URL is resolved as relative to the current path, i.e. the site root.The "tainted" branch in onAfterRoute() (lines 139-144) has the same unchecked Route::_() result.
The code is unchanged in 6.2-dev, 6.1-dev and 5.4-dev.
Suggested fix: bail out when the route can't be built, in both places:
$newRoute = Route::_($parsedVars, false);
if ($newRoute === null) {
return;
}There's no security impact: the redirect target is always the site root, and nothing is disclosed. It does cause error-log noise that anyone can trigger, and it breaks frontend non-SEF URLs of such components (e.g. URL-triggered tasks), which get redirected to the homepage instead of reaching the component.
I can test a PR if that helps.
| Labels |
Added:
No Code Attached Yet
|
||