fix(security_check): 目录型路径不再误判为脏授权
新增 _path_exists() 判断路径存在性(文件或目录,跟随软链)。 原 _resolve_file() 对 CRUD 目录/静态目录返回 None,被当成「文件不存在」→ 真实存在的目录误报脏授权。 (服务器端已验证的改动,按回传流程补提交)
This commit is contained in:
parent
8e09c5389a
commit
e756236272
@ -81,7 +81,12 @@ def _is_whitelisted(path):
|
|||||||
|
|
||||||
|
|
||||||
def _resolve_file(url_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('/')
|
rel = url_path.lstrip('/')
|
||||||
if not rel or '*' in rel or rel.endswith('%'):
|
if not rel or '*' in rel or rel.endswith('%'):
|
||||||
return None
|
return None
|
||||||
@ -91,11 +96,25 @@ def _resolve_file(url_path):
|
|||||||
for ext in ('.dspy', '.ui', '.xterm', '.html'):
|
for ext in ('.dspy', '.ui', '.xterm', '.html'):
|
||||||
if os.path.isfile(cand + ext):
|
if os.path.isfile(cand + ext):
|
||||||
return cand + ext
|
return cand + ext
|
||||||
if os.path.isdir(cand):
|
|
||||||
return None
|
|
||||||
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):
|
def _scan_file(fp):
|
||||||
try:
|
try:
|
||||||
src = open(fp, encoding='utf-8', errors='ignore').read()
|
src = open(fp, encoding='utf-8', errors='ignore').read()
|
||||||
@ -146,9 +165,9 @@ async def main(warn_only):
|
|||||||
continue
|
continue
|
||||||
fp = _resolve_file(path)
|
fp = _resolve_file(path)
|
||||||
if fp is None:
|
if fp is None:
|
||||||
# [C] 指向不存在的文件(脏数据);静态资源目录/根路径跳过
|
# [C] 指向不存在的路径(脏数据)。注意用 _path_exists 判存在性——
|
||||||
if path not in ('/', '') and not path.endswith(('.js', '.css', '.png', '.svg',
|
# 目录型路径(CRUD 目录、静态目录)不是单文件但真实存在,不算脏数据。
|
||||||
'.ico', '.woff', '.woff2', '.ttf')):
|
if not _path_exists(path):
|
||||||
findings['C'].append(path)
|
findings['C'].append(path)
|
||||||
continue
|
continue
|
||||||
if fp.endswith(('.js', '.css', '.png', '.svg', '.ico', '.md')):
|
if fp.endswith(('.js', '.css', '.png', '.svg', '.ico', '.md')):
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user