- core: MQ kill/exec 实际未禁用,修正错误声明;HttpTask.cpp 行号 L53→L58 - gateway: 更新 20+ 处行号偏移(_KEYGEN/handleProxy/is_safe_target 等) - aibox: shell=True 4处→3处,handle_connection/WebSocket 行号更新 - DEPS: WebSocketServer.cpp 已删除,fuzz 需求转移至 HttpServer_WsSession - 加固计划: Phase 1.1 (127.0.0.1 绑定) 标记为已完成 - captcha/libhttp: 修正轻微行号偏移
9.3 KiB
9.3 KiB
aibox 模块安全审计报告
审计日期: 2026-08-01
审计范围: aibox.py、skills/、WebSocket 服务、任务调度器、数据库
代码版本: dev_qing 分支
代码验证记录
验证日期: 2026-08-03
验证方式: 逐条对照审计报告与当前代码(aibox.py 358KB,关键区域 L3600-3850, L6300-6400, L7071-7160, L8600-8660)
验证结果汇总
| 等级 | 总数 | 已修复 | 部分修复 | 未修复 | 修复率 |
|---|---|---|---|---|---|
| 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 | ❌ | L3701, L3788, L6367 | shell=True 仍在 3 处使用,命令注入未修复 |
| P0-2 | ❌ | L1204, L8609 | 默认 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 | ⚠️ | L1609, L3617 | 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 | ⚠️ | L1204 | 默认 localhost(非 0.0.0.0 也非 127.0.0.1) |
| P3-5 | ❌ | - | 优雅关闭未验证 |
🔴 P0 — 严重问题
P0-1: 命令注入漏洞 ❌
-
位置:
aibox.pyL3701, L3788, L6367 -
风险描述:
# 当前危险实现(3处) 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) -
修复建议:
- 禁止
shell=True,改用subprocess.run([...], shell=False) - 将命令拆分为参数列表,使用
shlex.split()解析 - 添加命令白名单机制,只允许执行预定义的安全命令
- 限制工作目录,禁止在敏感目录执行命令
- 禁止
P0-2: WebSocket 无认证机制 ❌
-
位置:
aibox.pyL8609, L1204 -
风险描述:
- WebSocket 默认监听
localhost:8765(已从0.0.0.0收敛,但仍非127.0.0.1) handle_connection无任何 token、密码或 session 认证- 任何人连接后可无限制使用 DeepSeek API(消耗费用)
- 结合工具调用漏洞可直接控制服务器
- WebSocket 默认监听
-
修复建议:
- 短期方案: 将监听地址改为
127.0.0.1,通过 gateway/WAF 统一接入并认证 - 长期方案: WebSocket 握手阶段校验 token(支持 URL query 参数或 Authorization header)
- 参考现有 gateway 的认证机制(RSA签名/PBKDF2)做统一接入
- 添加 Origin 校验,防止跨站 WebSocket 劫持
- 短期方案: 将监听地址改为
🟠 P1 — 高危问题
P1-1: 路径遍历风险 ❌
-
位置:
aibox.pyL3943-3957(基类), L5999-6017(FileToolBase) -
风险描述:
check_path_safety仅检查文件大小,未做realpath前缀校验- 通过
../../etc/passwd可读取系统敏感文件 - 写入工具可覆盖任意文件,破坏系统或植入后门
-
修复建议:
- 定义允许访问的根目录(如
~/.aibox/workspace/) - 统一实现
safe_path()函数,realpath解析后校验前缀,确保在允许目录内 - 对写入操作添加额外确认或权限控制
- 定义允许访问的根目录(如
P1-2: SSRF 漏洞风险 ❌
-
位置:
aibox.pyL2037, 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 协议
- 跟随重定向时重新校验目标地址
- 禁止访问内网 IP 段:
P1-3: 敏感信息暴露 ❌
-
位置: 系统提示词构建 /
tools_info -
风险描述:
- 系统提示词中包含所有工具的完整参数 schema
- 错误响应可能返回栈追踪等内部信息
- 工具返回的原始错误信息可能泄露路径、代码结构
-
修复建议:
- 精简工具描述,只暴露必要信息
- 对外返回的错误信息做脱敏处理,仅返回通用错误提示
- 详细错误只记录在服务端日志
P1-4: API Key 配置校验缺失 ❌
-
位置:
aibox.pyL8326 -
风险描述:
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 | 缺少优雅关闭 | 关闭时未确保消息队列刷新、数据库连接正确关闭 |
✅ 已有安全机制
- ✅ 工具结果清洗:
_sanitize_tool_result过滤控制字符(L7080-7096) - ✅ OOM 防护:
MAX_OUTPUT_BYTES = 1MB,_read_with_limit截断输出(L3617-3670) - ✅ 工具结果大小限制:
TOOL_MAX_RESULT_LENGTH=100000截断(L1609, L7111) - ✅ 三层中断机制:
_is_cancelled+create_task异步解耦 + 连接关闭取消 Task(L6890, L8617, L8650) - ✅ fail-closed 设计: 工具异常时安全返回错误信息,不暴露内部状态(L7167 附近)
- ✅ 对话自动压缩: Token/消息数超限自动压缩,防止上下文无限增长(L1753-2202)
- ✅ 消息回滚机制: API 失败时
_rollback_messages回滚对话,防止坏消息污染历史 - ✅ 提示词软约束: 系统提示词中明确要求 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