# aibox 模块安全审计报告 **审计日期**: 2026-08-01 **审计范围**: `aibox.py`、`skills/`、WebSocket 服务、任务调度器、数据库 **代码版本**: dev_qing 分支 --- ## 代码验证记录 **验证日期**: 2026-08-03 **验证方式**: 逐条对照审计报告与当前代码(`aibox.py` 358KB,关键区域 L3600-3850, L6540-6740, L7071-7160, L8410-8470) ### 验证结果汇总 | 等级 | 总数 | 已修复 | 部分修复 | 未修复 | 修复率 | |------|------|--------|----------|--------|--------| | P0 | 2 | 0 | 0 | 2 | 0% | | P1 | 4 | 0 | 0 | 4 | 0% | | P2 | 6 | 0 | 0 | 6 | 0% | | P3 | 5 | 0 | 0 | 5 | 0% | | **合计** | **17** | **0** | **0** | **17** | **0%** | > **注意**: 原始审计报告(简化版)将 P0-1/P0-2 标记为"已修复",经代码验证实际均未修复。 ### 逐条验证 | 编号 | 状态 | 代码位置 | 验证说明 | |------|------|----------|----------| | P0-1 | ❌ | L3664, L3751, L6553, L6715 | `shell=True` 仍在 4 处使用,命令注入未修复 | | P0-2 | ❌ | L1177, L8423-8426 | 默认 `localhost:8765`(非 `127.0.0.1`),`handle_connection` 无任何认证 | | P1-1 | ❌ | L3943-3957, L5999-6017 | `check_path_safety` 仅检查文件大小,无 `realpath` 前缀校验 | | P1-2 | ❌ | L2037, L7365 | `requests.post` 无内网 IP 过滤 | | P1-3 | ❌ | 系统提示词 | 工具完整参数 schema 仍暴露 | | P1-4 | ❌ | L8326 | `api_key=None` 默认值,启动时未校验 | | P2-1 | ❌ | L7823 | `message_count` 仅统计未限流 | | P2-2 | ⚠️ | L1582, L3580 | `TOOL_MAX_RESULT_LENGTH=100000`,`MAX_OUTPUT_BYTES=1MB`(有缓解) | | P2-3 | ❌ | SQLite | 对话仍明文存储 | | P2-4 | ❌ | - | 临时文件清理未验证 | | P2-5 | ❌ | L4191-4251 | 技能 `.sh`/`.py` 直接加载执行 | | P2-6 | ❌ | - | 日志脱敏未验证 | | P3-1 | ❌ | - | 递归深度仍为 `max_recursion_depth=10` | | P3-2 | ❌ | - | 对话压缩可能丢失工具调用上下文 | | P3-3 | ❌ | - | 多连接竞争条件未加固 | | P3-4 | ⚠️ | L1177 | 默认 `localhost`(非 `0.0.0.0` 也非 `127.0.0.1`) | | P3-5 | ❌ | - | 优雅关闭未验证 | --- ## 🔴 P0 — 严重问题 ### P0-1: 命令注入漏洞 ❌ - **位置**: `aibox.py` L3664, L3751, L6553, L6715 - **风险描述**: ```python # 当前危险实现(4处) subprocess.Popen(command, shell=True, ...) subprocess.run(command, shell=True, capture_output=True, text=True) ``` 使用 `shell=True` 并通过 f-string 直接拼接用户输入的命令,攻击者(或被诱导的AI)可以构造恶意命令执行任意系统操作: - `rm -rf /` 删除所有文件 - `cat /etc/shadow` 窃取密码哈希 - 反弹 shell 完全控制系统 - **已有缓解**: `MAX_OUTPUT_BYTES = 1MB` 限制输出大小(L3580) - **修复建议**: 1. 禁止 `shell=True`,改用 `subprocess.run([...], shell=False)` 2. 将命令拆分为参数列表,使用 `shlex.split()` 解析 3. 添加命令白名单机制,只允许执行预定义的安全命令 4. 限制工作目录,禁止在敏感目录执行命令 ### P0-2: WebSocket 无认证机制 ❌ - **位置**: `aibox.py` L8423-8426, L1177 - **风险描述**: - WebSocket 默认监听 `localhost:8765`(已从 `0.0.0.0` 收敛,但仍非 `127.0.0.1`) - `handle_connection` 无任何 token、密码或 session 认证 - 任何人连接后可无限制使用 DeepSeek API(消耗费用) - 结合工具调用漏洞可直接控制服务器 - **修复建议**: 1. **短期方案**: 将监听地址改为 `127.0.0.1`,通过 gateway/WAF 统一接入并认证 2. **长期方案**: WebSocket 握手阶段校验 token(支持 URL query 参数或 Authorization header) 3. 参考现有 gateway 的认证机制(RSA签名/PBKDF2)做统一接入 4. 添加 Origin 校验,防止跨站 WebSocket 劫持 --- ## 🟠 P1 — 高危问题 ### P1-1: 路径遍历风险 ❌ - **位置**: `aibox.py` L3943-3957(基类), L5999-6017(FileToolBase) - **风险描述**: - `check_path_safety` 仅检查文件大小,未做 `realpath` 前缀校验 - 通过 `../../etc/passwd` 可读取系统敏感文件 - 写入工具可覆盖任意文件,破坏系统或植入后门 - **修复建议**: - 定义允许访问的根目录(如 `~/.aibox/workspace/`) - 统一实现 `safe_path()` 函数,`realpath` 解析后校验前缀,确保在允许目录内 - 对写入操作添加额外确认或权限控制 ### P1-2: SSRF 漏洞风险 ❌ - **位置**: `aibox.py` L2037, L7365 - **风险描述**: - `requests.post` 未限制可访问的 IP 范围 - 可访问内网服务:`http://127.0.0.1:8443`(gateway)、`http://10.x.x.x` 等 - 可访问云服务商元数据接口(如 `http://169.254.169.254/` 获取临时凭证) - **修复建议**: - 禁止访问内网 IP 段:`127.0.0.0/8`, `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, `169.254.0.0/16` - 禁止访问非 HTTP/HTTPS 协议 - 跟随重定向时重新校验目标地址 ### P1-3: 敏感信息暴露 ❌ - **位置**: 系统提示词构建 / `tools_info` - **风险描述**: - 系统提示词中包含所有工具的完整参数 schema - 错误响应可能返回栈追踪等内部信息 - 工具返回的原始错误信息可能泄露路径、代码结构 - **修复建议**: - 精简工具描述,只暴露必要信息 - 对外返回的错误信息做脱敏处理,仅返回通用错误提示 - 详细错误只记录在服务端日志 ### P1-4: API Key 配置校验缺失 ❌ - **位置**: `aibox.py` L8326 - **风险描述**: - `api_key=None` 默认值,启动时未校验 `DEEPSEEK_API_KEY` - 可能因配置错误导致空 Key 或使用默认无效 Key - 没有 Key 时直接启动失败或行为异常 - **修复建议**: - 启动时强制校验 `DEEPSEEK_API_KEY` 配置 - 未配置有效 Key 时直接拒绝启动并给出明确提示 - 日志中不要打印完整 API Key --- ## 🟡 P2 — 中危问题 | # | 问题 | 位置 | 风险 | 建议 | |---|------|------|------|------| | P2-1 | 无请求频率限制 | L7823 | 恶意用户可高频发送请求,导致 API 费用暴涨 | 添加 per-connection 消息频率限制(如每分钟 30 轮) | | P2-2 | 工具调用结果大小限制 | L1582, L3580 | 已有 `TOOL_MAX_RESULT_LENGTH=100000` 和 `MAX_OUTPUT_BYTES=1MB`,但大文件读取仍可能超限 | 统一工具输出限制,超出截断并提示 | | P2-3 | 对话历史明文存储 | SQLite | 聊天记录含敏感信息,明文存储易被窃取 | 加密存储或限制数据库文件权限 | | P2-4 | 临时文件清理不彻底 | 代码执行工具 | 执行代码生成的临时文件未清理,占用磁盘或泄露信息 | 使用 `tempfile.TemporaryDirectory()` 自动清理 | | P2-5 | 技能加载无沙箱 | L4191-4251 | 可执行技能(`.sh`/`.py`)直接运行,无隔离或校验 | 技能目录权限校验,仅加载可信来源,或沙箱执行 | | P2-6 | 日志未脱敏 | Logger | API 请求/响应、对话内容可能写入日志,泄露敏感信息 | 日志中脱敏 API Key、密码等敏感字段 | --- ## 🟢 P3 — 低危/健壮性问题 | # | 问题 | 说明 | |---|------|------| | P3-1 | 递归深度防护不足 | `max_recursion_depth=10`,复杂工具链仍可能导致栈溢出,建议改用迭代 | | P3-2 | 对话压缩可能丢失上下文 | 简单截断早期消息,可能丢失工具调用上下文,建议保留工具调用/结果对 | | P3-3 | 多线程竞争风险 | `messages`/`tools` 等状态在多连接下可能有竞争条件 | | P3-4 | 监听地址非 `127.0.0.1` | 默认 `localhost`(已从 `0.0.0.0` 收敛,但建议改为 `127.0.0.1`) | | P3-5 | 缺少优雅关闭 | 关闭时未确保消息队列刷新、数据库连接正确关闭 | --- ## ✅ 已有安全机制 1. ✅ **工具结果清洗**: `_sanitize_tool_result` 过滤控制字符(L7071-7087) 2. ✅ **OOM 防护**: `MAX_OUTPUT_BYTES = 1MB`,`_read_with_limit` 截断输出(L3580-3630) 3. ✅ **工具结果大小限制**: `TOOL_MAX_RESULT_LENGTH=100000` 截断(L1582, L7153-7155) 4. ✅ **三层中断机制**: `_is_cancelled` + `create_task` 异步解耦 + 连接关闭取消 Task(L7106, L8431, L8445) 5. ✅ **fail-closed 设计**: 工具异常时安全返回错误信息,不暴露内部状态(L7127-7130) 6. ✅ **对话自动压缩**: Token/消息数超限自动压缩,防止上下文无限增长(L1700-1740) 7. ✅ **消息回滚机制**: API 失败时 `_rollback_messages` 回滚对话,防止坏消息污染历史 8. ✅ **提示词软约束**: 系统提示词中明确要求 AI 不要执行危险命令(需配合代码层面硬约束) --- ## 🛠️ 修复路线图 ### 第一阶段(立即):P0 - [ ] 移除所有 `shell=True`,改用参数列表 `subprocess.run([...])` - [ ] WebSocket 绑定 `127.0.0.1`,添加 token 认证或通过 gateway 统一接入 ### 第二阶段(近期):P1 - [ ] `check_path_safety` 添加 `realpath` 前缀校验,限制工作目录 - [ ] 网络请求添加 SSRF 防护(内网 IP 黑名单) - [ ] 启动时强制校验 `DEEPSEEK_API_KEY` - [ ] 错误信息脱敏,详细错误仅记录服务端日志 ### 第三阶段(后续版本):P2/P3 - [ ] 添加 per-connection 消息频率限制 - [ ] 日志脱敏、对话加密存储 - [ ] 临时文件自动清理、技能加载沙箱化 - [ ] 多线程安全加固、优雅关闭 --- **审计完成时间**: 2026-08-01 **代码验证时间**: 2026-08-03