18 Commits
Author SHA1 Message Date
qing 67acae708c fix(aibox): Batch N 波次4+5 LLM 健壮性与权限隔离,Batch N 收束
波次 4 LLM 健壮性(T10/T19/T20/T21/T23 + T14 复现证伪):
- T10 调度器 await 改 wait_for 硬超时兜底(task_timeout+30s 宽限),
  软取消够不到的卡死路径不再永久停摆调度循环
- T19 FailoverClient 异常收窄为瞬时白名单(Connection/Timeout/
  ChunkedEncoding),MissingSchema 等永久配置错误不再污染冷却表
- T20 流式未收到 [DONE] 抛 TransientLLMError,回答无声截断可感知
- T21 env 覆盖黑名单 filter_env_overrides(LD_*/DYLD_*/PATH 等),
  executors 两处 + process_manager 接入
- T23 压缩后 tool 配对双向修复(失配 tool_calls 剥离防 API 400)
- T14 FTS5 复现证伪:JOIN 别名场景表名 MATCH 正常,无需修复

波次 5 权限隔离(T22/T-L17/T-L18;T1/T2 产品决策:仅告警/维持现状):
- T22a TOOL_PROFILE_TASK 定时任务精简工具面(无 update_identity/
  update_soul/set_proxy)
- T22b ProcessManager owner 隔离:bg_write/bg_kill 属主校验,
  观察面共享;DeepSeekChat 新增 owner_id 传导
- T1 绑定非回环地址时启动显著告警
- T-L17 model_config env 名按域名推荐(防跨厂商凭据外发)
- T-L18 list_profiles 过滤控制字符(防 ANSI 注入)

测试:test_n_fixes.py 增至 62 项;全量 598 passed / 1 failed
(Windows 向 ping 用例,环境项),零回归。审计报告补记 §24.7~24.11,
README 同步 owner 隔离语义。八轮审计 T 系列 28 项全部处置完毕。
2026-08-21 14:53:42 +00:00
qing 2dc79f0637 fix(aibox): Batch N 波次3 平台兼容(T3/T11/T25/T26/T27)
- T3 basic_tools 平台感知引用与 Windows 指引:_quote_arg 按 os.name
  分支(Windows 双引号包裹,拒绝双引号/换行/%变量名% 注入形态);
  ReadFile/WriteFile/ListFiles/Web 四工具 Windows 走 PowerShell/
  curl.exe 等价命令(WriteFile 用 Base64 规避 cmd 换行/转义限制)
- T11 executors 与 process_manager 的 _terminate_tree Windows 分支
  改 taskkill /T /F 递归收割进程树,兜底单进程 kill
- T25 MemoryDatabase 统一 _connect 工厂(busy_timeout=10000),
  7 处直连替换,对齐 MemoDatabase J9
- T26 SkillManager._load_skills 原子替换 self.skills(对齐
  PromptManager M6),reload 期间不再读到空/半截技能表
- T27 atomic_write_text 对 PermissionError 做 3 次退避重试

测试:新增 tests/test_n_fixes.py 30 项;全量 566 passed / 1 failed
(Windows 向 ping 用例,环境项),零回归。审计报告补记 §24.5/§24.6。
2026-08-21 13:56:33 +00:00
qing 5894e64287 fix(aibox): Batch N 波次1~2——第八轮审计 T 系列速赢与并发正确性修复
波次1 速赢批(7 项):
- T8 ProcessManager watermark 取号与回显记账原子化(entry.lock 改 RLock)
- T9 LLM 非 200 响应抛出前 close,流式路径清 _current_response
- T13 _sanitize_log_msg 增加裸 sk- key 脱敏,异常构造点统一过脱敏
- T12 流式判定改共享 saw_complete 标志(排空后 empty() 恒 False 死逻辑),
  超长截断前移堵住非流式直发绕过 N8 输出预算
- T16/T17 三处 Popen 显式 encoding=utf-8 + errors=replace
- T18 detach/log_file/force 统一过 _coerce_bool(字符串 "false" 误判)

波次2 并发正确性批(6 项):
- T4 registry 输出队列入口快照,不再向共享工具实例传播(跨会话串扰)
- T5 executor 单槽 _current_process 改令牌多槽注册表,_terminate_tree
  显式传 (proc, pgid),finally 只注销自己槽位(防并发误杀进程组)
- T6 FailoverClient 冷却键改 id(client),与 P6 去重键语义一致
- T7 stream_chat 拆普通方法+内部生成器,消除生成器延迟副作用清除取消标志
- T15 工具结果统一 TOOL_MAX_RESULT_LENGTH 截断(两条分支同口径)
- T24 非流式 execute() timeout 下限夹取 1s(该路径无 3600s 兜底)

测试:532 passed / 4 failed(平台环境项)/ 1 skipped,零回归
审计报告补记 §23 第八轮审计 + §24 Batch N 波次1~2 修复记录
2026-08-21 17:33:33 +08:00
qing 3e6e171831 fix(aibox): Batch M 波次5 客户端收尾(M1~M5/M7/M8)
- voice_client: stdin 单守护线程+Queue 替代每行 to_thread(泄漏/丢行);
  arecord 探测 timeout=5 + finally 清理临时文件
- client: main() finally 统一 disconnect websocket
- model_config: 主循环捕获 EOF/KeyboardInterrupt;api 节非 dict 重置;
  fallback 字符串规整(展示/删除清理);api_key_env 正则校验+
  显示字段拒控制字符限长
- 冒烟 7/7 通过;全量 493 passed/4 failed(既有平台项)/1 skipped 零回归
- 审计报告补 §22,Batch M 五波次收束
2026-08-20 14:40:00 +08:00
qing d1357ae483 fix(aibox): Batch M 波次4 命令面输入规整(W1~W8/W11/W12+W5)
- W1: WS 三入口 action/command/content 非 str 规整;task title/content 类型拦截
- W2: task add delay float 转换+[0,10年]钳制+友好 error
- W3: task complete 缺 task_id 回 error(新增 i18n 键)
- W4: /search 空关键词回用法提示,不再 LIKE %% 全表刷屏
- W5: main() 暂存 _cli_overrides,/reload 重放并回包注明,不再静默丢 CLI 覆盖
- W6: 启动失败 sys.exit(1);--port argparse 1~65535 校验
- W7: --scheduler-interval 统一 max(0.1,v) 钳制
- W8: --temperature main() 入口 [0.0,2.0] 钳制
- W11: config system/scheduler 节非 dict 回退默认节
- W12: --memo-add title strip/空串→None;db.add_memo 标题非空 ValueError

冒烟 12/12 通过;测试 493 passed/4 failed(既有平台项)/1 skipped 零回归
2026-08-20 13:54:36 +08:00
qing 9db2bc112d fix(aibox/frontend): Batch M 波次3 前端功能修复(F1/F2/F3/F4/F6)
- F1: entry/frontend 清空按钮先 cloneNode 缓存 welcome-message 再清空,修 TypeError 中断
- F2: 三页面手动断开清除/作废重连定时器,杜绝连接复活(entry 新增 reconnectTimer 句柄)
- F3: 三页面连接前关闭 CONNECTING 中旧连接,防孤儿连接/双后端会话
- F4: 6 个 CDN CSS link 补 SRI integrity+crossorigin(sha384 实测计算)
- F6: frontend 重连文案与 3000*N 实际延迟对齐

三页面内联脚本 node --check 通过;测试 493 passed/4 failed(既有平台项)/1 skipped 零回归
2026-08-20 13:25:12 +08:00
qing 9064750f33 fix(aibox/skills): Batch M 波次2 路径边界收口(S2/S3/S6/S9/S10/S11/S12/S13)
- gitclient: delete 限工作区内 .git 仓库(S2);分支名白名单防选项注入(S3)
- camera/screenshot: --filename 拒绝分隔符/绝对路径/父目录引用(S9/S10)
- facerec: person_name 白名单(兼容中文)接入 add/remove/get-info(S11)
- vision: 图片魔数白名单校验,data URL MIME 按实测类型(S12)
- sftp-transfer: listdir 条目名双向过滤防恶意服务端目录逃逸(S6)
- test-auto-appimage: exec_name 白名单防 sed 替换注入(S13)

测试 493 passed / 4 failed(既有平台环境项)/ 1 skipped,零回归
2026-08-20 13:11:07 +08:00
qing 5dc5ec9af2 fix(aibox/skills): Batch M 波次1 凭据收口(S1/S4/S5/S7/S8)
凭据不再进命令行 argv/会话日志,对齐 SKILLS_FORMAT.md J12 条例:
- gitclient: token 改经 GIT_CONFIG_* 环境变量传 http.extraheader(git>=2.31),不再嵌入 clone URL(不进 .git/config);新增 _scrub_token 输出统一脱敏
- ssh-exec: 移除 -p/--password,密码仅经环境变量 AIBOX_SSH_PASS 提供
- sftp-transfer: 移除 -p/--password,AIBOX_SFTP_PASS 优先、getpass 兜底,密钥认证不再强制索密码
- aes-crypto: 移除 --key,密钥仅经 --key-file/--load-key 文件途径;生成密钥不再打印明文;save_key_iv 写后 chmod 600

验证:py_compile 通过;aes 生成/加载/加解密闭环实测正常,--key 被拒绝;全量测试 493 passed / 4 failed(平台环境项)/ 1 skipped,与基线一致。审计报告 §17 结论 + §18 波次1修复记录同步。
2026-08-20 12:29:34 +08:00
qing e43aeeaf44 fix(aibox): Batch L - round-6 audit low-risk fixes (R1~R3)
- R1: /memos WS command tolerates malformed reminder_time (J1 gap)

- R2: handle_interrupt no longer cancels global CLI executor

- R3: unregister closes websocket + cancels in-flight processing tasks

- tests: 6 new cases in test_l_fixes.py, 493 passed on Windows

- docs: round-6 audit report section 16, README sync (all 72 findings fixed)
2026-08-20 11:46:47 +08:00
qing 7dc6796f3a docs: reorganize aibox audit report - overview table, full conclusions, final state
Add a rounds overview table (baseline HEAD / findings / fix batch /
test baseline per round), extend the overall conclusion to cover all
five rounds, and append a final-state section consolidating high-risk
disposition, maintained/deferred items, and the 490-test baseline.
Fix Batch H item count (13 -> 19) to match the fix table.
2026-08-20 11:19:04 +08:00
qing 2c6d1e8ce6 docs: record round-5 audit and batch K fixes in aibox report and README
审计报告追加第五轮(§13 发现 J1~J16 + §14 波次 1~5 落地记录),
README 同步测试清单与计数(490 项全过)。
2026-08-19 07:01:22 +08:00
qing 31b2a4d6ca docs: batch I audit fixes record in aibox audit report
Batch I (remaining-item sweep): 10 fixes landed, 16 new tests
(test_i_fixes.py), 424 passed. Q7a / M4 / Q9 / F8 kept as-is with
rationales recorded.
2026-08-18 03:09:18 +00:00
qing 9fee9a1478 docs: batch H audit fixes record in aibox audit report
Fourth round (HEAD d1f780e): 3-way parallel review + main-reviewer
verification + Linux PoC 6/6; 13 fixes landed, 26 new tests
(test_h_fixes.py), 408 passed.
2026-08-18 02:33:34 +00:00
qing acb6ddbb4c docs: batch G audit fixes record in aibox audit report
Add round-3 audit (section 9): legacy item re-verification (17 items), v3.4 multi-model profile + L4 failover review (P1-P7), architecture compliance matrix. Add batch G fix record (section 10): 17 fixes across 5 waves, 20 new regression tests, full suite 375 passed.
2026-08-18 07:21:34 +08:00
qing 5bcf22f9a7 fix(aibox): registry timeout cleanup + reader thread finalization (F2/N6+N4)
N6: both streaming-forward timeout paths (deadline hit, join(5)
expiry) previously returned early and skipped the
tool.streaming_output / tool.output_queue cleanup, leaving the daemon
thread writing through the instance attribute — zombie output could
leak into the next session's queue once the attribute got reassigned.
Now unified through a timed_out flag with cleanup at the single exit;
stream_tool_timeout becomes an instance attribute (3600s default,
test-tunable).

N4: reader-thread finalization after timeout/grace break. First
implementation followed the audit suggestion (close stdout + join),
but PoC regression proved close() blocks: CPython stream objects hold
an internal lock, so closing while readline is blocked parks until
readline returns (PoC-1 regressed 3s -> 15.2s, exactly the
Start-Sleep duration). Corrected strategy: when reader already got
EOF, close stdout to release the pipe fd; when reader is still
blocked, only join(timeout=2) then give up (daemon-bounded, thread
ends naturally when the grandchild exits and EOF arrives), keeping
the main flow prompt. Audit report updated with this correction.

Tests: new tests/test_f2_fixes.py (5 cases), PoC regression 5/5
(PoC-1/4 back to ~5s), full suite 272 passed.
2026-08-17 22:47:37 +08:00
qing eb88a77238 fix(aibox): never persist SOCKS5 proxy password to disk (F1/N1, +N11)
- config.set_proxy gains password_env (aligned with api_key_env
  convention): config file persists only the env var name; plaintext
  password lives in memory for the current session only
- _save_config deep-copies and nulls proxy.socks5.password before
  json.dump, so every save path is sanitized (defense in depth)
- get_proxy resolves password as in-memory plaintext first, then via
  password_env from os.environ; downstream consumers (llm_client,
  web tool curl args) unchanged
- legacy migration on load: plaintext found on disk is kept in memory
  for the session, file is immediately rewritten sanitized
- SetProxyTool exposes password_env and reports password source
- registry debug logs mask password/api_key/token/secret/authorization
  kwargs (N11)

Tests: new tests/test_config.py (3 cases: no plaintext on save,
password_env resolution, legacy migration); full suite 267 passed.
Audit report updated with Batch F progress.
2026-08-17 22:37:30 +08:00
qing 1348660cd8 docs(aibox): second-round audit re-review at HEAD 177a9ac
- Batch E fixes re-verified: H1/H3/M1 solid, H2 solid but with two
  residuals (reader thread leak, subagent timeout blind spot), M2
  incomplete (timeout paths skip tool attribute cleanup)
- Legacy M3/M4/L1/L3 confirmed unfixed; L1 found second instance at
  db.py:459 (get_immediate_memos)
- New findings: 1 high (SOCKS5 proxy password persisted in plaintext),
  9 medium (drain thread leak, event-loop blocking RLock, FTS5 keyword
  injection, streaming bypass of result length cap, persistent prompt
  injection storage, TOCTOU on mark_as_triggered, etc.), 7 low
- Updated compliance matrix and proposed Batch F fix plan (F1-F6)
2026-08-17 17:51:43 +08:00
qing 177a9ac9a6 fix(aibox): close audit findings H1-H3/M1-M2 (command exec protection chain)
- H1: CommandLineTool.execute_streaming now purely delegates to injected
  executor; removes 150-line duplicate Popen loop that bypassed 1MB cap,
  cancel() and timeout protections
- H2: thread the blocking readline into a daemon reader thread; main loop
  polls queue with 0.1s ticks so timeout/1MB checks fire even for silent
  commands (verified: 3s timeout on 15s sleep, was 15s+ before)
- H3: stdin=DEVNULL on both Popen sites; stdin-waiting commands now hit
  EOF instead of deadlocking the tool thread forever
- M1: heredoc delimiter uniquification in write_file guidance (content
  line equal to AIBOX_EOF no longer truncates into shell injection)
- M2: 3600s total deadline on registry streaming forward loop

Verification: PoC regression 5/5 PASS (timeout/1MB/cancel/delegation),
full unit suite 264 passed. Audit report updated with Batch E results.
2026-08-17 17:28:41 +08:00