Skip to content

fix+refactor: 安全漏洞修复 & 架构师审查改进#11

Merged
Mola-maker merged 3 commits into
mainfrom
claude/refactor-loop-fix-LOy8S
May 8, 2026
Merged

fix+refactor: 安全漏洞修复 & 架构师审查改进#11
Mola-maker merged 3 commits into
mainfrom
claude/refactor-loop-fix-LOy8S

Conversation

@Mola-maker
Copy link
Copy Markdown
Owner

概述

本 PR 包含两轮改动:

  1. Code Review 发现的 6 处安全/逻辑 Bug 修复
  2. 架构师审查后的 6 项结构性改进

所有修改均保持接口兼容,不破坏现有功能,python -c "from ui.server import app" 及所有核心模块导入验证通过。


Commit 1:安全漏洞与逻辑 Bug 修复

# 文件 严重度 问题 修复
1 agents/utils.py:44 CRITICAL docker_exec 不捕获 subprocess.TimeoutExpired,所有调用方超时时直接崩溃 try/except TimeoutExpired → 返回 (-1, "", "timed out")
2 ui/server.py:636 HIGH GET /api/figures/{filename} 路径穿越:../../etc/passwd 可读任意文件 Path.resolve() + 安全根目录前缀校验
3 ui/server.py:1354 HIGH /api/pip-install shell 注入:旧过滤仅查 5 个字符,\n(>< 等仍可逃逸 包名正则白名单 ^[A-Za-z0-9_.\-\[\]]+$ + shlex.quote()
4 sandbox/loop.py:53 MEDIUM 成功时报 iterations: 0(0-indexed),失败时报 iteration+1(1-indexed) 统一改为 iteration + 1
5 sandbox/healer.py:51 MEDIUM 超过最大迭代次数返回 is_logic=True,误触发不必要的 P2 回滚 超限返回 is_logic=False
6 agents/conversation_mgr.py LOW [:28]/[:60].strip(),全空白内容不回退 "新对话" .strip()

Commit 2:架构师审查改进

P1 — asyncio 锁防竞态(ui/server.py

  • 新增 _pipeline_lock / _sandbox_lock / _chat_lock 三把 asyncio.Lock
  • run_phase / stop_pipeline / /api/clear 均在锁内完成 check-then-Popen,消除 TOCTOU 窗口
  • _execute_chat_actions 改为 async defpause/restart/sandbox_* 各分支持对应锁
  • _dispatch_tool 改为 async def,调用处加 await

P2 — 跨进程原子写(agents/events.py

  • emit() 改用 os.open(O_WRONLY|O_APPEND|O_CREAT) + os.write()
  • Linux 上单次 write() 对 <4096 B 常规文件是原子操作,消除两个进程交错写入导致的 JSONL 行损坏
  • reset() 改用 O_TRUNC 截断,消除 write_text("") 的先清空再写窗口

P3 — 日志尾读 OOM 修复(ui/server.py

  • /api/logs 不再 read_text() 整个文件后 [-10000:]
  • 改为 seek(size - 10_000) 读最多 10 KB,文件无论多大内存消耗恒定

P4 — MAX_ITER 权威来源统一(sandbox/loop.py

  • execute_with_healing() 调用新增 _load_max_iter()
  • 优先读 config/pipeline.jsonmax_heal_iterations,回退环境变量
  • Dashboard 的配置修改现在真正影响 healing 循环次数(之前被忽略)

P5 — load_all() 真正幂等(agents/extensions/registry.py

  • ExtensionRegistry 新增 _loaded: bool 字段
  • load_all() 入口短路检查,防止 FastAPI startup + 手动调用双重加载导致 tools/plugins 重复注册

P6 — /api/chat 防抖(ui/server.py

  • 3 秒冷却窗口,双击提交返回 429 Too Many Requests

测试清单

  • 所有核心模块导入无报错
  • from ui.server import app 正常
  • git diff --stat 确认只改动 7 个文件,无意外变更

https://claude.ai/code/session_01Ff2zH5qmZkJ4kCQAKh1TXx


Generated by Claude Code

claude added 3 commits May 7, 2026 16:45
P1 ui/server.py — asyncio 锁防竞态
  - 新增 _pipeline_lock / _sandbox_lock / _chat_lock 三把 asyncio.Lock
  - run_phase / stop_pipeline / /api/clear 均在锁内做 check-then-Popen
  - _execute_chat_actions 改为 async,pause/restart/sandbox_* 分支各持对应锁
  - _dispatch_tool 改为 async,调用处 await;chat endpoint 同步 await

P2 agents/events.py — 跨进程原子追加
  - emit() 改用 os.open(O_WRONLY|O_APPEND|O_CREAT) + os.write();
    单次 write() 在 Linux 上对 <4096 B 的常规文件写入是原子的
  - reset() 改用 O_TRUNC 截断,避免 write_text() 的先清空再写入窗口

P3 ui/server.py — /api/logs OOM 修复
  - 不再 read_text() 整个文件后取尾部;改为 seek(size-10000) 读最多 10 KB

P4 sandbox/loop.py — MAX_ITER 权威来源统一
  - execute_with_healing() 调用新增的 _load_max_iter()
  - 优先读 pipeline.json 中的 max_heal_iterations,回退到环境变量
  - Dashboard 的配置现在真正影响 healing 循环次数

P5 agents/extensions/registry.py — load_all() 真正幂等
  - ExtensionRegistry 新增 _loaded: bool 字段
  - load_all() 入口处检查并短路,防止二次调用重复追加 plugins/tools/skills

P6 ui/server.py — /api/chat 防抖
  - 新增 3 秒冷却窗口,双击提交返回 429

https://claude.ai/code/session_01Ff2zH5qmZkJ4kCQAKh1TXx
- agents/model_router.py: import tomllib 改为 try/except 兼容导入
  (tomllib 为 Python 3.11+ 标准库;3.8-3.10 回退到 tomli)
- .github/workflows/pylint.yml: 安装 tomli,加 --fail-under=8.0
  使 CI 在代码质量分低于 8.0 时才失败,当前得分 8.95/10

https://claude.ai/code/session_01Ff2zH5qmZkJ4kCQAKh1TXx
ui/server.py
- _LazyLock 替代模块级 asyncio.Lock(),首次 acquire 时才绑定事件循环
  (修复 Python 3.8/3.9 下 uvicorn 创建新 loop 导致 Lock 绑定错误 loop 的问题)
- _sandbox_output_buf 改为 collections.deque(maxlen=200),消除手动切片
- asyncio.get_event_loop() → get_running_loop()(3.10+ 废弃修复,共 3 处)
- /api/logs: stat()+open() 两步改为 open()+fstat() 单文件句柄,消除 TOCTOU
- get_figure: startswith() 路径安全检查改为 relative_to() try-except,
  消除路径前缀假阳性(/foo/b 误匹配 /foo/bar)
- _call 闭包内移除 sys.path.insert(无效:BASE 已在运行时 cwd)

agents/utils.py
- 新增 load_toml(path) 公共辅助函数,utf-8-sig 编码兼容 Windows BOM,
  try/except tomllib → tomli 回退

agents/model_router.py
- 使用 agents.utils.load_toml 替代内联 try/except 兼容导入 + 手动读取
- _load_routes() 简化为两行

pylint 评分: 8.96/10 (+0.01)

https://claude.ai/code/session_01Ff2zH5qmZkJ4kCQAKh1TXx
@Mola-maker Mola-maker merged commit 9fdc24a into main May 8, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants