An authenticated path traversal in assets/icon allows local SVG file read by passing traversal sequences in the extension parameter. The issue is caused by file existence checks happening before extension validation.
Details
The endpoint:
src/controllers/AssetsController.php:1115-1123
actionIcon(string $extension) calls Assets::iconPath($extension) and returns sendFile($path, ...).
In Assets::iconPath():
Path is built from user-controlled extension:
src/helpers/Assets.php:906-909
If file_exists($path) is true, path is returned immediately:
src/helpers/Assets.php:910-912
Validation exists in Assets::iconSvg():
preg_match('/^\w+$/', $extension)
src/helpers/Assets.php:927-931
However, that validation is only reached if iconPath() does not find a file.
So traversal payloads that resolve to existing .svg files bypass validation and are served by sendFile().
Impact
Authenticated users can read local .svg files accessible to the application process.