From e2fc130f994ef3fa126c3ebb8056bac88ee11d3d Mon Sep 17 00:00:00 2001 From: wangwangit Date: Tue, 19 May 2026 12:06:21 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20XSS=20=E9=A3=8E=E9=99=A9=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - showToast 改用 textContent 设置消息内容,防止 HTML 注入 - createHoverText 对所有用户输入进行 escapeHtml 转义 - 续订/支付历史/编辑支付模态框中的 subscription.name 和 payment.note 使用 escapeHtml 转义 - debug 页面 adminUsername 转义 - 添加全局 escapeHtml 工具函数 --- src/api/debug.js | 2 +- src/views/adminPage.html | 25 ++++++++++++++++--------- src/views/configPage.html | 3 ++- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/api/debug.js b/src/api/debug.js index 1adff08..7aa69b7 100644 --- a/src/api/debug.js +++ b/src/api/debug.js @@ -38,7 +38,7 @@ async function handleDebug(request, env) {

配置信息

配置存在: ${debugInfo.configExists ? '✓' : '✗'}

-

管理员用户名: ${debugInfo.adminUsername}

+

管理员用户名: ${String(debugInfo.adminUsername || '').replace(//g, '>')}

JWT密钥: ${debugInfo.hasJwtSecret ? '✓' : '✗'} (长度: ${debugInfo.jwtSecretLength})

diff --git a/src/views/adminPage.html b/src/views/adminPage.html index 19a09c1..04fbf2d 100644 --- a/src/views/adminPage.html +++ b/src/views/adminPage.html @@ -734,6 +734,12 @@ return response; } + // HTML 转义,防止 XSS + function escapeHtml(str) { + if (!str) return ''; + return String(str).replace(/&/g,'&').replace(//g,'>').replace(/"/g,'"').replace(/'/g,'''); + } + // 农历转换工具函数 - 前端版本 const lunarCalendar = { // 农历数据 (1900-2100年) @@ -1039,7 +1045,8 @@ const lunarBiz = { type === 'error' ? 'exclamation-circle' : type === 'warning' ? 'exclamation-triangle' : 'info-circle'; - toast.innerHTML = '
' + message + '
×'; + toast.innerHTML = '
×'; + toast.querySelector('.toast-msg').textContent = message; container.appendChild(toast); setTimeout(() => toast.classList.add('show'), 50); @@ -1147,12 +1154,12 @@ const lunarBiz = { // 创建带悬浮提示的文本元素 function createHoverText(text, maxLength = 30, className = 'text-sm text-gray-900') { if (!text || text.length <= maxLength) { - return '
' + text + '
'; + return '
' + escapeHtml(text) + '
'; } - const truncated = text.substring(0, maxLength) + '...'; + const truncated = escapeHtml(text.substring(0, maxLength)) + '...'; return '
' + - '
' + + '
' + truncated + '
' + '
' + @@ -1778,7 +1785,7 @@ const lunarBiz = { '
' + '
' + '

' + - ' 手动续订 - ' + subscription.name + + ' 手动续订 - ' + escapeHtml(subscription.name) + '

' + '