Medium severity6.5NVD Advisory· Published Oct 10, 2025· Updated Apr 15, 2026
CVE-2025-60868
CVE-2025-60868
Description
The Alt Redirect 1.6.3 addon for Statamic fails to consistently strip query string parameters when the "Query String Strip" feature is enabled. Case variations, encoded keys, and duplicates are not removed, allowing attackers to bypass sanitization. This may lead to cache poisoning, parameter pollution, or denial of service.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
alt-design/alt-redirectPackagist | < 1.6.4 | 1.6.4 |
Affected products
1- Range: <=1.6.3
Patches
15dc6753c7151Fix - CVE-2025-60868
2 files changed · +31 −46
src/Helpers/URISupport.php+4 −39 modified@@ -4,61 +4,26 @@ namespace AltDesign\AltRedirect\Helpers; -use Illuminate\Support\Arr; use Illuminate\Support\Str; class URISupport { /** - * Returns the current URI with named Query Strings filtered out . + * Returns the current URI without any query strings for redirect matching. * * @return string $uri */ public static function uriWithFilteredQueryStrings() : string { $request = request(); - $data = new Data('query-strings'); - $withoutQueryStrings = Arr::pluck($data->all(), 'query_string'); - // Filter out unwanted params, then strip the base url to get a filtered uri - $encoding = str_contains($request->getRequestURI(), '+') - ? PHP_QUERY_RFC1738 - : PHP_QUERY_RFC3986; + // Return just the path without any query parameters + // Query parameters will be handled separately in redirectWithPreservedParams return Str::replace( $request->root(), '', - self::fullUrlWithoutQuery($withoutQueryStrings, $encoding) + $request->url() ); } - /** - * Replacement for fullUrlWithoutQuery() in Request to use custom Arr::query() implementation - * - * @param array $keys - * @param int $encoding_type (optional) Encoding Type - * @return string - */ - private static function fullUrlWithoutQuery(array $keys, $encoding_type = PHP_QUERY_RFC1738) : string - { - $request = request(); - $query = Arr::except($request->query(), $keys); - - $question = $request->getBaseUrl().$request->getPathInfo() === '/' ? '/?' : '?'; - - return count($query) > 0 - ? $request->url().$question.self::myArrQuery($query, $encoding_type) - : $request->url(); - } - - /** - * Replacement for Arr::query() to use default encoding method - * - * @param array $array - * @param int $encoding_type (optional) Encoding Type - * @return string - */ - private static function myArrQuery(array $array, $encoding_type = PHP_QUERY_RFC1738) : string - { - return http_build_query($array, '', '&', $encoding_type); - } }
src/Http/Middleware/CheckForRedirects.php+27 −7 modified@@ -65,19 +65,39 @@ public function handle(Request $request, Closure $next, string ...$guards): Resp private function redirectWithPreservedParams($to, $status) { - $preserveKeys = []; + $stripKeys = []; foreach ((new Data('query-strings'))->all() as $item) { - if (!($item['strip'] ?? false)) { - $preserveKeys[] = $item['query_string']; + if ($item['strip'] ?? false) { + $stripKeys[] = strtolower($item['query_string']); } } + // Parse raw query string to handle double-encoding and duplicates + $rawQueryString = request()->getQueryString(); $filteredStrings = []; - foreach(request()->all() as $key => $value) { - if (!in_array($key, $preserveKeys)) { - continue; + $seenKeys = []; + + if ($rawQueryString) { + // Decode the query string recursively to handle multiple levels of encoding + $decodedQueryString = $rawQueryString; + $previousQueryString = ''; + + // Keep decoding until no more changes occur (handles double/triple encoding) + while ($decodedQueryString !== $previousQueryString) { + $previousQueryString = $decodedQueryString; + $decodedQueryString = urldecode($decodedQueryString); + } + + parse_str($decodedQueryString, $parsedParams); + + foreach($parsedParams as $key => $value) { + $normalizedKey = strtolower($key); + // Strip only parameters marked with strip:true, preserve all others + if (!in_array($normalizedKey, $stripKeys) && !isset($seenKeys[$normalizedKey])) { + $seenKeys[$normalizedKey] = true; + $filteredStrings[] = sprintf("%s=%s", urlencode($key), urlencode($value)); + } } - $filteredStrings[] = sprintf( "%s=%s", $key, $value); } if ($filteredStrings) {
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6- github.com/advisories/GHSA-rpjr-pcmr-9ppwghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-60868ghsaADVISORY
- gist.github.com/kasiasok/870933de18d1400fa8be88e1bcadec6cnvdWEB
- github.com/alt-design/Alt-Redirect-Addon/commit/5dc6753c7151ac994c63e18914998991b1f65cbdghsaWEB
- github.com/alt-design/Alt-Redirect-Addon/releases/tag/v1.6.4ghsaWEB
- statamic.com/addons/alt-design/alt-redirects/release-notesnvdWEB
News mentions
0No linked articles in our index yet.