fix(aibox): round-5 audit batch K - max_turns clamp, task input validation, XSS hardening, atomic writes, broadcast timeout
第五轮审计(J1~J16)全量修复 + 子代理 max_turns 钳制: - 子代理 max_turns 钳制(0/None 回退默认 10,负数钳制 1)+ 14 项回归测试 - J1 任务系统投毒:add_memo 入库校验(时间/间隔/类型)、调度器预检与触发事务 防御、展示路径兜底、register 移入 try、add_user_task 补 repeat_end_time 透传 - J2/J13 前端 XSS:三页面 marked 输出经 DOMPurify 净化、entry1 系统消息/任务 分隔条改 textContent、CDN 脚本补 SRI - J3 FTS 删除换序(先 fts 后内容表,索引不再残留) - J5 原子写推广:新增 common/atomic.py(mkstemp+fsync+os.replace),config/prompt/ history 全部接入;损坏配置备份后回退 - J6 单例初始化加锁(PromptManager/ConfigManager 并发首例不双重加载) - J7 broadcast 并发发送 + wait_for 超时回收僵死连接 - J4/J8/J9~J12/J14~J16:验证异常脱敏、交互输入容错、MemoDatabase WAL+busy_timeout、 memo 批量删除、/new 竞态、skills 引号转义、voice_client 清理、死代码移除、 skill_manager 同名键/help 截断
This commit is contained in:
1 parent
f4fcf175ec
commit
457bb900fb
22 files changed
+1147
-126
No files matched your search
@@ -27,6 +27,9 @@ class SkillManager:
|
||||
2. Markdown 文件 (.md):第一行为简介(# 标题或普通文本),其余为技能内容
|
||||
"""
|
||||
|
||||
# J16(审计 2026-08-19):--help 输出上限——内容会进系统提示词
|
||||
MAX_HELP_LENGTH = 2000
|
||||
|
||||
def __init__(self, logger: Optional[Logger] = None):
|
||||
self.logger = logger or Logger("SkillManager")
|
||||
# name -> {path, file, summary, content, is_markdown}
|
||||
@@ -38,7 +41,11 @@ class SkillManager:
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def _run_help(self, skill_path: str) -> str:
|
||||
"""执行 skill_path --help 并返回完整输出(stdout 优先,否则 stderr)。"""
|
||||
"""执行 skill_path --help 并返回完整输出(stdout 优先,否则 stderr)。
|
||||
|
||||
J16(审计 2026-08-19):输出截断到 MAX_HELP_LENGTH——技能 --help
|
||||
输出会进系统提示词,异常/恶意脚本可撑爆上下文。
|
||||
"""
|
||||
try:
|
||||
result = subprocess.run(
|
||||
[skill_path, "--help"],
|
||||
@@ -50,6 +57,8 @@ class SkillManager:
|
||||
output = result.stdout.strip()
|
||||
if not output:
|
||||
output = result.stderr.strip()
|
||||
if len(output) > self.MAX_HELP_LENGTH:
|
||||
output = output[:self.MAX_HELP_LENGTH] + "\n…(已截断)"
|
||||
return output
|
||||
except Exception as e:
|
||||
self.logger.warning(f"运行 {skill_path} --help 失败: {e}")
|
||||
@@ -129,12 +138,26 @@ class SkillManager:
|
||||
and not f.startswith('.')
|
||||
]
|
||||
|
||||
for skill_file in skill_files:
|
||||
# J16(审计 2026-08-19):同名键冲突(foo 可执行文件与 foo.md)此前
|
||||
# 由 listdir 顺序决定谁覆盖谁,行为不确定。改为可执行优先 + 确定性:
|
||||
# 先加载可执行技能,Markdown 遇到已占用的同名键时跳过并告警
|
||||
executable_files = [
|
||||
f for f in skill_files
|
||||
if not self._is_markdown_file(f)
|
||||
]
|
||||
markdown_files = [f for f in skill_files if self._is_markdown_file(f)]
|
||||
|
||||
for skill_file in executable_files + markdown_files:
|
||||
skill_path = os.path.join(skills_dir, skill_file)
|
||||
skill_name = os.path.splitext(skill_file)[0]
|
||||
is_markdown = self._is_markdown_file(skill_file)
|
||||
|
||||
if is_markdown:
|
||||
if skill_name in self.skills:
|
||||
self.logger.warning(
|
||||
f"Markdown 技能 '{skill_file}' 与同名可执行技能冲突,已跳过"
|
||||
f"(可执行技能优先)")
|
||||
continue
|
||||
# Markdown 格式技能:直接读取内容
|
||||
summary, content = self._read_markdown_skill(skill_path)
|
||||
if content:
|
||||
|
||||
Reference in new issue
Block a user