From 4fe65b088e8c0042924a10a3a3afd289eed27a2e Mon Sep 17 00:00:00 2001 From: "Dr.Lt.Data" Date: Fri, 14 Aug 2026 08:18:46 +0900 Subject: [PATCH 1/2] fix(ui): surface the server's reason for a batch 404 (#3128) The batch install/uninstall paths replaced the server's 404 body with a false "default channel" lead. Drop the 404 branch so a 404 falls through to the existing server-text path; uninstall never returns 404 anyway. Fixes #3128 (section 1), reported by plz12345. --- js/common.js | 2 -- js/custom-nodes-manager.js | 2 -- 2 files changed, 4 deletions(-) diff --git a/js/common.js b/js/common.js index 30af9c12..7cf33477 100644 --- a/js/common.js +++ b/js/common.js @@ -663,8 +663,6 @@ export async function uninstallNodes(nodeList, options = {}) { if (res.status == 403) { errorMsg += `This action is not allowed with this security level configuration.\n`; - } else if (res.status == 404) { - errorMsg += `With the current security level configuration, only custom nodes from the "default channel" can be uninstalled.\n`; } else { errorMsg += await res.text() + '\n'; } diff --git a/js/custom-nodes-manager.js b/js/custom-nodes-manager.js index 9b7917e6..abe5f36c 100644 --- a/js/custom-nodes-manager.js +++ b/js/custom-nodes-manager.js @@ -1480,8 +1480,6 @@ export class CustomNodesManager { } catch { errorMsg += `This action is not allowed with this security level configuration.\n`; } - } else if(res.status == 404) { - errorMsg += `With the current security level configuration, only custom nodes from the "default channel" can be installed.\n`; } else { errorMsg += await res.text() + '\n'; } From 98be899011f0c6b9626a8f2bdb16122b7bdc9748 Mon Sep 17 00:00:00 2001 From: "Dr.Lt.Data" Date: Sat, 15 Aug 2026 07:47:36 +0900 Subject: [PATCH 2/2] harden(ui): escape untrusted text before the batch error dialog (#3128) The dialog renders HTML, so run the server body and the pack title (registry-derived) through the existing sanitizeHTML() at both sites. The title is wrapped in String() so a missing title can't throw inside the error handler; rendered text is unchanged for ordinary values. --- js/common.js | 4 ++-- js/custom-nodes-manager.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/js/common.js b/js/common.js index 7cf33477..5c82259e 100644 --- a/js/common.js +++ b/js/common.js @@ -659,12 +659,12 @@ export async function uninstallNodes(nodeList, options = {}) { }); if (res.status != 200) { - errorMsg = `'${nodeItem.title || nodeItem.name}': `; + errorMsg = `'${sanitizeHTML(String(nodeItem.title || nodeItem.name))}': `; if (res.status == 403) { errorMsg += `This action is not allowed with this security level configuration.\n`; } else { - errorMsg += await res.text() + '\n'; + errorMsg += sanitizeHTML(await res.text()) + '\n'; } break; diff --git a/js/custom-nodes-manager.js b/js/custom-nodes-manager.js index abe5f36c..1963ae60 100644 --- a/js/custom-nodes-manager.js +++ b/js/custom-nodes-manager.js @@ -1467,7 +1467,7 @@ export class CustomNodesManager { }); if (res.status != 200) { - errorMsg = `'${item.title}': `; + errorMsg = `'${sanitizeHTML(String(item.title))}': `; if(res.status == 403) { try { @@ -1481,7 +1481,7 @@ export class CustomNodesManager { errorMsg += `This action is not allowed with this security level configuration.\n`; } } else { - errorMsg += await res.text() + '\n'; + errorMsg += sanitizeHTML(await res.text()) + '\n'; } break;