- Advisory: GHSA-9vx2-j98c-p72w · CVE-2026-75594
- Affected:
getkirby/cms≤ 4.9.4 and 5.0.0 – 5.5.1 · Fixed: 4.9.5 / 5.5.2 - Severity: High · CWE-22 (Path Traversal)
- Status: publicly disclosed and fixed. Reported by Pig-Tail through coordinated disclosure; credited in the vendor advisory.
Only servers that accept encoded slashes (%2f) in the request path: nginx, PHP's built-in
server, or Apache with AllowEncodedSlashes enabled. Apache's default configuration, and any server
hardened against encoded slashes, is not affected.
Kirby's media handler serves files from the media directory, generating thumbnails on demand.
Each parent (a page, for instance) owns a media directory, and each thumbnail requires a prepared
job file — a .json metadata file — before the handler will generate it. The handler searches
for the requested file inside the parent's media directory.
In the affected releases the filename component was not confined to that directory. Where the
attacker can smuggle encoded slashes into the request, the lookup traverses out of the parent's
media directory and reaches arbitrary paths on the server — including paths outside the site's
index root.
Two distinct primitives:
- Existence oracle for arbitrary
.jsonfiles. The response differs between an existing and a non-existing thumbnail configuration, so an attacker can probe whether any given.jsonfile exists anywhere the web user can read — addressed as a relative path from the media directory of any existing parent. - Thumbnail generation from arbitrary media. For an existing
.jsonfile that happens to be a valid job file (a validfilenamekey), the handler generates a thumbnail of the referenced media file and deletes the job file in the process — so the primitive reads image content from outside the site root and destroys the file it rode in on.
In 4.9.5 and 5.5.2, Kirby\Cms\Media::thumb() rejects any filename containing path information —
anything that is not a plain filename — before it is appended to the validated root. The
file::version component was additionally hardened to block paths containing ../.
Verification needs a Kirby site served by a stack that permits %2f in the path (nginx or
php -S), plus a readable .json path to target. Point the media route at a parent that exists and
walk out of its media directory with encoded separators; the differing response for present vs.
absent .json files is the oracle.
Write-up only. No runnable PoC is published here — the primitive deletes the job file it resolves, so a canned harness against a real site is destructive by construction. Refer to the linked advisory for full detail and the fixed versions.