fix: loop the :// strip in detaintPath so it cannot be re-formed

detaintPath() and detaintPathAllowAbsolute() removed '://' with a single
str_replace() while the '../' removal below them already looped. One
pass is not enough, because removing a match can join its neighbours
into a fresh match: '::////' collapses to '://'. So
'php::////filter/read=string.rot13/resource=/etc/passwd' came back out
of the filter as 'php://filter/read=string.rot13/resource=/etc/passwd',
reinstating exactly the wrapper the strip exists to remove.

Loop the '://' removal the same way the '../' removal is looped. These
functions guard $view, $request, $action, the modal name and skin file
paths.

Refs GHSA-wgqf-6fjf-7gxw.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Isaac Connor
2026-07-19 13:13:06 -04:00
parent 6daa135e53
commit c5f24a1d1f

View File

@@ -1823,8 +1823,12 @@ function generateConnKey() {
}
function detaintPathAllowAbsolute($path) {
// Strip out :// because php:// is a way to inject code apparently
$path = str_replace('://', '', $path);
// Strip out :// because php:// is a way to inject code apparently.
// This must loop: a single pass lets the removal re-form the sequence it
// just removed, so '::////' collapses back into '://'.
do {
$path = str_replace('://', '', $path, $count);
} while($count);
// Remove any absolute paths, or relative ones that want to go up
do {
$path = str_replace('../', '', $path, $count);
@@ -1834,8 +1838,12 @@ function detaintPathAllowAbsolute($path) {
function detaintPath($path) {
// Strip out :// because php:// is a way to inject code apparently
$path = str_replace('://', '', $path);
// Strip out :// because php:// is a way to inject code apparently.
// This must loop: a single pass lets the removal re-form the sequence it
// just removed, so '::////' collapses back into '://'.
do {
$path = str_replace('://', '', $path, $count);
} while($count);
// Remove any absolute paths, or relative ones that want to go up
do {
$path = str_replace('../', '', $path, $count);