From 214bf4708332f98203130c08af09acf0168374ed Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Thu, 17 Sep 2026 06:16:15 +0200 Subject: [PATCH] fix: prevent uncontrolled redirect on /go/app/download The `/go/app/download/` endpoint has a parameter `url` which is intended for internal use on this site, but the parameter was not validated, so it could be abused for random redirects to any site. Now requires the url to point to downloads.keyman.com; a more comprehensive fix could remove the hostname altogether from the redirector and just have a path (but this mitigates for now). Test-bot: skip --- go/app/download.php | 6 ++++++ go/package/download.php | 3 +++ 2 files changed, 9 insertions(+) diff --git a/go/app/download.php b/go/app/download.php index 91554bcb..5704ea9e 100644 --- a/go/app/download.php +++ b/go/app/download.php @@ -30,6 +30,12 @@ class AppDownloadPage { public static function redirect_to_file($url, $product, $version, $tier) { if(empty($url)) { JsonApiFailure::InvalidParameters("url"); + return; + } + + if(!preg_match("/^https?:\/\/downloads\\.keyman(-staging)?\\.com(\\.localhost)?\//", $url)) { + JsonApiFailure::Failure(400, JsonApiFailure::ERROR_InvalidParameters, "url parameter must start with downloads.keyman.com"); + return; } if(empty($product)) { diff --git a/go/package/download.php b/go/package/download.php index c76f09d1..eca631cb 100644 --- a/go/package/download.php +++ b/go/package/download.php @@ -35,10 +35,12 @@ public static function redirect_to_file($type, $id, $version, $platform, $tier, if($type !== 'keyboard' && $type !== 'model') { JsonApiFailure::InvalidParameters("type"); + return; } if(empty($id)) { JsonApiFailure::InvalidParameters("id, version"); + return; } if(empty($version)) { @@ -50,6 +52,7 @@ public static function redirect_to_file($type, $id, $version, $platform, $tier, if(empty($json)) { JsonApiFailure::Failure(404, JsonApiFailure::ERROR_NotFound, "$type package with id $id was not found"); + return; } $version = $json->version;