From 609fdccdae032f8734654cb57e14a081726b463c Mon Sep 17 00:00:00 2001 From: blaipr Date: Thu, 24 Sep 2026 15:16:37 +0200 Subject: [PATCH] fix: a dropped file's name reaches a toast as text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit toasts.min.js renders every message with innerHTML, deliberately, since messages carry
separators — so whatever is concatenated into one has to be escaped first. The file upload's two rejection messages concatenated the dropped File's name and type raw, and a file named that tripped either check ran its handler. It is the user's own local file, so on its own this is self-XSS, reachable only by persuading somebody to upload a crafted name. It is fixed because the sink is real and the fix is one expression: $("
").text(value).html() at both call sites. The wider issue is left for a separate decision: app-main.min.js routes a server's description and messages into the same innerHTML, and app-requests.min.js puts a failed request's entire responseText there, while ActionResponse strings are not escaped the way templates are. --- public/js/app-util.min.js | 4 +- .../View/FileNamesReachToastsAsTextTest.php | 85 +++++++++++++++++++ 2 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 tests/Unit/Infrastructure/Adapter/In/Web/View/FileNamesReachToastsAsTextTest.php diff --git a/public/js/app-util.min.js b/public/js/app-util.min.js index dcee249fd..4221da305 100644 --- a/public/js/app-util.min.js +++ b/public/js/app-util.min.js @@ -13,7 +13,7 @@ checkLevel:function(b){a.info("password:checkPassLevel");this.config.passLength= b?d():a.info("Notifications disabled")})}}};return{decodeEntities:function(a){return $("