LowGHSA-c43v-4cr8-6mvpCVE-2026-56394

Craft CMS has authenticated path traversal in `assets/icon`, allowing local `.svg` file read

Published 9 Jul 2026 · Updated 6 Aug 2026

Affected packages

craftcms/cmsComposer
Affected
>=4.0.0-RC1 <4.17.7
Fixed in
4.17.7
Update to the fixed version for your release line, for example:composer require craftcms/cms:^4.17.7
craftcms/cmsComposer
Affected
>=5.0.0-RC1 <5.9.13
Fixed in
5.9.13
Update to the fixed version for your release line, for example:composer require craftcms/cms:^5.9.13

Details

Summary

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.

References

  • https://github.com/craftcms/cms/commit/30f5f1a8d6edf0f3a00be72c42c78d9dc7d72d5c

Is GHSA-c43v-4cr8-6mvp in any of your client repos?

Checking one package by hand is fine. Checking it across forty client projects is not. NPMscan reads the lockfiles in every GitHub repo you pick, finds each project with an affected craftcms/cms, and gives you the command that fixes it.

References

Advisory data from OSV.dev (opens OSV.dev in a new tab), refreshed daily.