From e756236272add2f970554edf1c982158feb8115f Mon Sep 17 00:00:00 2001 From: yumoqing Date: Tue, 25 Aug 2026 15:27:33 +0800 Subject: [PATCH] =?UTF-8?q?fix(security=5Fcheck):=20=E7=9B=AE=E5=BD=95?= =?UTF-8?q?=E5=9E=8B=E8=B7=AF=E5=BE=84=E4=B8=8D=E5=86=8D=E8=AF=AF=E5=88=A4?= =?UTF-8?q?=E4=B8=BA=E8=84=8F=E6=8E=88=E6=9D=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增 _path_exists() 判断路径存在性(文件或目录,跟随软链)。 原 _resolve_file() 对 CRUD 目录/静态目录返回 None,被当成「文件不存在」→ 真实存在的目录误报脏授权。 (服务器端已验证的改动,按回传流程补提交) --- scripts/security_check.py | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/scripts/security_check.py b/scripts/security_check.py index e715d1f..5f990bc 100644 --- a/scripts/security_check.py +++ b/scripts/security_check.py @@ -81,7 +81,12 @@ def _is_whitelisted(path): def _resolve_file(url_path): - """URL 路径 → wwwroot 下的实际文件(含无扩展名回退)。找不到返回 None。""" + """URL 路径 → wwwroot 下的实际文件(含无扩展名回退)。找不到返回 None。 + + 注意:目录型路径(CRUD 目录如 /discount/discount_list、静态目录如 /bricks) + 返回 None 表示「不是单文件」,判断「路径是否存在」必须用 _path_exists(), + 不能用本函数的 None 当作「文件不存在」——否则会把真实存在的目录误判成脏授权。 + """ rel = url_path.lstrip('/') if not rel or '*' in rel or rel.endswith('%'): return None @@ -91,11 +96,25 @@ def _resolve_file(url_path): for ext in ('.dspy', '.ui', '.xterm', '.html'): if os.path.isfile(cand + ext): return cand + ext - if os.path.isdir(cand): - return None return None +def _path_exists(url_path): + """URL 路径在 wwwroot 下是否真实存在(文件 或 目录,跟随软链)。""" + rel = url_path.lstrip('/') + if not rel: + return True # 根路径 + if '*' in rel or rel.endswith('%'): + return True # 通配授权另有 B 类检查 + cand = os.path.join(WWWROOT, rel) + if os.path.exists(cand): # os.path.exists 跟随软链,且覆盖目录 + return True + for ext in ('.dspy', '.ui', '.xterm', '.html'): + if os.path.exists(cand + ext): + return True + return False + + def _scan_file(fp): try: src = open(fp, encoding='utf-8', errors='ignore').read() @@ -146,9 +165,9 @@ async def main(warn_only): continue fp = _resolve_file(path) if fp is None: - # [C] 指向不存在的文件(脏数据);静态资源目录/根路径跳过 - if path not in ('/', '') and not path.endswith(('.js', '.css', '.png', '.svg', - '.ico', '.woff', '.woff2', '.ttf')): + # [C] 指向不存在的路径(脏数据)。注意用 _path_exists 判存在性—— + # 目录型路径(CRUD 目录、静态目录)不是单文件但真实存在,不算脏数据。 + if not _path_exists(path): findings['C'].append(path) continue if fp.endswith(('.js', '.css', '.png', '.svg', '.ico', '.md')):