CVE-2026-75592 Overview
CVE-2026-75592 is a path containment bypass in Kirby, an open-source PHP content management system. The flaw resides in Kirby's media handler, where Kirby\Filesystem\Dir::realpath() and Kirby\Filesystem\F::realpath() performed a string-prefix comparison without enforcing a directory separator boundary. A remote attacker can invoke Kirby\Cms\Media::thumb() to reach a PHP-readable sibling directory that shares the intended root's name prefix, such as /var/www/site2 next to /var/www/site. When that directory contains a valid .json thumbnail job file, the attacker can generate and access thumbnails from images in the sibling location and delete the job file during processing. This weakness maps to CWE-22 (Path Traversal).
Critical Impact
Remote unauthenticated attackers can access image content and delete thumbnail job files in adjacent sites, exposing staging environments, backups, or co-hosted internal sites.
Affected Products
- Kirby CMS versions prior to 4.9.5 (4.x release line)
- Kirby CMS versions prior to 5.5.2 (5.x release line)
- Deployments where sibling directories share a name prefix with the Kirby media root
Discovery Timeline
- 2026-08-31 - CVE-2026-75592 published to NVD
- 2026-09-01 - Last updated in NVD database
Technical Details for CVE-2026-75592
Vulnerability Analysis
The vulnerability stems from an incomplete filesystem containment check in Kirby's realpath helpers. Both Dir::realpath() in src/Filesystem/Dir.php and F::realpath() in src/Filesystem/F.php verified containment with substr($realpath, 0, strlen($parent)) !== $parent. This comparison accepts any path that begins with the parent string, including sibling paths that share the same name prefix. A parent of /var/www/site therefore matches /var/www/site2, /var/www/site-backup, and similar directories.
The issue becomes exploitable through Kirby\Cms\Media::thumb(). The method concatenates a caller-supplied $filename to the validated $root and then reads a job file at $root . '/.jobs/' . $filename . '.json'. Because the root check accepted sibling directories, an attacker can steer processing toward image files in an unrelated directory that Kirby was never intended to serve.
Root Cause
The root cause is a missing DIRECTORY_SEPARATOR boundary in the containment check. Prefix matching without a trailing separator conflates a directory with any sibling whose name starts with the same characters. The Media::thumb() handler also did not require $filename to be a plain basename, allowing untrusted input to influence file paths appended to the trusted root.
Attack Vector
Exploitation is remote and unauthenticated over the network. An attacker crafts a request to the Kirby media route referencing a filename for which a valid .json job file exists inside a sibling directory that shares the media root's name prefix. Kirby resolves the sibling path, generates a thumbnail from an image in that directory, returns it to the attacker, and deletes the job file as part of processing.
// Patch: src/Filesystem/Dir.php – enforce separator boundary in realpath()
// require a path separator boundary so that
// a sibling directory sharing the same name prefix
// (e.g. `/site2` for the parent `/site`)
// cannot pass the containment check
$parent = rtrim($parent, '/\\');
if (
$realpath !== $parent &&
str_starts_with($realpath, $parent . DIRECTORY_SEPARATOR) === false
) {
throw new Exception('The directory is not within the parent directory');
}
// Source: https://github.com/getkirby/kirby/commit/2b6fab950bc89d505ea89576bf71c8de614cc3b2
// Patch: src/Cms/Media.php – reject non-basename filenames in Media::thumb()
// $filename is appended unmodified to the validated root
// to build the thumbnail and job file paths;
// it must be a plain filename without any path information
if (
$filename === '' ||
$filename === '.' ||
$filename === '..' ||
basename($filename) !== $filename
) {
throw new InvalidArgumentException();
}
$thumb = $root . '/' . $filename;
$job = $root . '/.jobs/' . $filename . '.json';
// Source: https://github.com/getkirby/kirby/commit/e0dca5f709adc21b36f5549df2c0619bc59da56c
Detection Methods for CVE-2026-75592
Indicators of Compromise
- Web server access logs showing requests to /media/ paths that resolve to files outside the intended Kirby site root.
- Unexpected deletions of .json files under .jobs/ directories of adjacent sites on the same host.
- HTTP 200 responses returning thumbnails whose source image resides in a sibling directory such as site2 when only site is served.
Detection Strategies
- Inspect Kirby application logs and PHP error output for NotFoundException: The thumbnail configuration could not be found bursts, which can indicate probing.
- Correlate media URL patterns with filesystem access events to flag reads that cross the configured site root boundary.
- Review deployed Kirby versions across all hosts and alert on any instance below 4.9.5 or 5.5.2.
Monitoring Recommendations
- Enable filesystem auditing on directories adjacent to Kirby media roots to capture read and unlink operations by the PHP process user.
- Track outbound response payload hashes from media endpoints to identify content served from unexpected paths.
- Monitor the Kirby GitHub Security Advisory GHSA-6j4c-mgqr-qv76 for updated guidance.
How to Mitigate CVE-2026-75592
Immediate Actions Required
- Upgrade Kirby to version 4.9.5 on the 4.x line or version 5.5.2 on the 5.x line.
- Inventory shared hosts and identify Kirby site roots that share a name prefix with adjacent directories, such as site and site2.
- Audit .jobs/ directories across co-hosted sites for missing or unexpectedly deleted .json files.
Patch Information
The fix lands in two commits. Commit 2b6fab9 tightens Dir::realpath() and F::realpath() to require a DIRECTORY_SEPARATOR boundary using str_starts_with($realpath, $parent . DIRECTORY_SEPARATOR). Commit e0dca5f adds a basename check in Media::thumb(), rejecting $filename values that contain path information or equal . or ... Both fixes ship in Kirby 4.9.5 and 5.5.2.
Workarounds
- Rename co-hosted site directories so that no sibling shares a name prefix with a Kirby media root (for example, rename site2 to staging-alt).
- Restrict PHP process filesystem access using open_basedir or systemd ReadOnlyPaths and InaccessiblePaths to prevent reads outside the intended site root.
- Isolate each Kirby installation under a separate operating system user or container so the web process cannot read adjacent site content.
# php.ini per-site hardening to constrain filesystem access
[PATH=/var/www/site]
open_basedir = "/var/www/site/:/tmp/"
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

