逐模块对照实际代码验证审计报告中的问题修复状态,添加代码验证记录、逐条验证结果、修复率统计。合并aibox两份审计报告,删除重复文件。修复率:confs 61% > dnfs 60% > ai_review 50% > smtp 37.5% > db 33% > core 12.5% > gateway 12.5% > pymsg 6.25% > static 5% > captcha/aibox/BotOps 0%
8.3 KiB
8.3 KiB
confs 模块安全审计报告
审计日期: 2026-08-01
审计范围: confs/confs.py、confs/log_client.py、confs/_run.sh、confs/_set.sh、pymsg/pymsg/rpc.py(RPC 框架依赖层)
审计人: AI Security Audit
代码验证记录
验证日期: 2026-08-03
验证方式: 逐条对照审计报告与当前代码(confs.py、log_client.py、_run.sh、_set.sh、requirements.txt)
验证结果汇总
| 等级 | 总数 | 已修复 | 未修复 | 修复率 |
|---|---|---|---|---|
| P0 | 1 | 1 | 0 | 100% |
| P1 | 7 | 7 | 0 | 100% |
| P2 | 4 | 2 | 2 | 50% |
| P3 | 6 | 1 | 5 | 17% |
| 合计 | 18 | 11 | 7 | 61% |
逐条验证(已修复)
| 编号 | 代码位置 | 验证说明 |
|---|---|---|
| P0 Slowloris | confs.py L262 |
使用 RpcServer,recv_timeout 默认 10s |
| P1 文件大小限制 | confs.py L48, L137-139 |
MAX_CONFIG_SIZE = 1 MiB,读取前校验 |
| P1 log_client 线程异常 | log_client.py L150-153 |
_on_error 捕获异常,线程不崩溃 |
| P1 TOCTOU | confs.py L104-115, L117-150 |
_resolve_locked 在锁内完成 realpath→stat→open |
| P1 reload falsy值 | confs.py L319-331 |
None/非字符串/空字符串分别处理 |
| P1 get() 浅拷贝 | confs.py L136, L150 |
返回 dict(entry) 防缓存污染 |
| P1 list() realpath | confs.py L167-171 |
符号链接解析后校验前缀 |
| P1 key 类型校验 | confs.py L300-303 |
非字符串明确报错 |
| P2 interpolation | confs.py L221 |
interpolation=None 禁用 %(key)s |
| P2 argparse | confs.py L347 |
描述已更新为 "pymsg RpcServer/TCP" |
| P3-1 sleep 2 | _run.sh L5 |
已移除,直接 exec python3 confs.py |
逐条验证(未修复)
| 编号 | 状态 | 代码位置 | 验证说明 |
|---|---|---|---|
| P2-3 | ❌ 未修复 | confs.py L149, L296, L306 |
配置名/key 直接拼入日志,未过滤 \n/ANSI 控制字符 |
| P2-4 | ❌ 未修复 | confs.py L159-181 |
list() 持锁期间遍历目录+stat,但文件数极少可接受 |
| P3-2 | ❌ 未修复 | _set.sh L5 |
仍硬编码清华 pip 镜像源 |
| P3-3 | ❌ 未修复 | _set.sh |
缺少 set -e,pip install 失败后继续执行 |
| P3-4 | ❌ 未修复 | requirements.txt L2 |
仍包含运行时不需要的 nuitka 编译工具 |
| P3-5 | ❌ 未修复 | confs.py L206-247 |
ConfigParser section 大小写敏感/option 不敏感的隐式行为未文档化 |
| P3-6 | ❌ 未修复 | confs.py L144 |
底层 IO 异常信息原样返回给调用方 |
一、模块概述
confs 是微服务架构中的统一配置分发服务,基于 pymsg RpcServer 在 127.0.0.1:8010 提供 TCP RPC 接口,集中管理各微服务的配置文件,通过内存缓存 + 文件 mtime 自动重载机制向内部服务分发配置。
核心组件:
ConfigStore:配置文件仓库(磁盘目录 + 内存缓存 + 自动重载)ConfsServer:RPC 服务入口,路由分发_extract_key():INI/JSON 单键提取功能log_client.py:异步日志推送客户端(副本,与其他服务同步)
二、已修复问题(本次审计周期内)
| # | 问题 | 级别 | 修复提交 | 状态 |
|---|---|---|---|---|
| 1 | pymsg recv() 无超时导致主线程永久阻塞(Slowloris DoS) |
P0 | 9708fbc |
✅ 已修复 |
| 2 | 配置文件读取无大小限制,超大文件导致 OOM | P1 | da7f11d |
✅ 已修复 |
| 3 | log_client 后台线程异常无保护,异常可杀死线程导致内存无限增长 | P1 | 1b9c727 |
✅ 已修复(4份副本同步) |
| 4 | example_log_client.py 仍使用旧 MsgClient 接口与当前 RpcServer 不匹配 |
P1 | bdbea6a |
✅ 已修复 |
| 5 | ConfigStore.get() TOCTOU 竞态:锁外 _resolve() 后锁内 open() 存在符号链接替换窗口 |
P1 | 9efb96e |
✅ 已修复 |
| 6 | log_client 日志时间戳在 _send() 时生成而非入队时,队列积压时时间不准确 |
P2 | 1b9c727 |
✅ 已修复 |
| 7 | log_client flush() 固定 sleep(0.6) 不可靠 |
P2 | 1b9c727 |
✅ 已修复 |
| 8 | log_client 队列无上限,线程异常时内存无限增长 | P2 | 1b9c727 |
✅ 已修复 |
| 9 | _handle_reload 空字符串/非字符串 name(falsy 值)意外清空全部缓存 |
P1 | b53d499 |
✅ 已修复 |
| 10 | ConfigStore.get() 返回缓存 dict 可变引用,调用方可污染缓存 |
P1 | b53d499 |
✅ 已修复 |
| 11 | list() 不对符号链接做 realpath 校验,可探测外部文件元信息 |
P1 | b53d499 |
✅ 已修复 |
| 12 | _handle_get 中 key 参数未做类型校验,非字符串值被 str() 转换后产生误导行为 |
P1 | b53d499 |
✅ 已修复 |
| 13 | ConfigParser 未禁用插值(%(key)s),含裸 % 的配置值触发 InterpolationError |
P2 | b53d499 |
✅ 已修复 |
| 14 | argparse 描述字符串未与顶部文档同步更新(pymsg/TCP → pymsg RpcServer/TCP) |
P2 | b53d499 |
✅ 已修复 |
三、遗留问题
🔴 P0 — Critical
无遗留 P0 问题。
🟠 P1 — High
无遗留 P1 问题。
🟡 P2 — Medium(建议修复)
P2-1 ConfigParser 未禁用插值 ✅ 已修复
P2-2 argparse 描述字符串未与文档同步更新 ✅ 已修复
P2-3 日志注入风险
文件: confs/confs.py 第 148/282/288 行
配置名和 key 直接拼入日志消息,若包含 \n 或 ANSI 转义序列可伪造日志条目。防御纵深角度建议过滤控制字符。
P2-4 list() 在持锁期间遍历目录并 stat 每个文件
配置文件数量预计极少(<100),实际影响可忽略,但若未来扩展到大量文件需考虑优化。
🔵 P3 — Low(改进建议)
| # | 问题 | 文件 | 说明 |
|---|---|---|---|
| P3-1 | _run.sh 无意义 sleep 2 |
confs/_run.sh L5 |
启动前固定 sleep 是 hack,应通过 core 的 init.txt 依赖顺序或健康检查保证 |
| P3-2 | _set.sh 硬编码清华 pip 镜像源 |
confs/_set.sh L5 |
非中国大陆网络环境下安装可能失败 |
| P3-3 | _set.sh 缺少 set -e |
confs/_set.sh |
pip install 失败后脚本继续执行,可能导致运行时 ImportError |
| P3-4 | requirements.txt 包含运行时不需要的 nuitka |
confs/requirements.txt |
nuitka 是编译工具(且在 _set.sh 中被注释掉),不应作为运行时依赖 |
| P3-5 | ConfigParser section 大小写敏感/option 大小写不敏感的隐式行为 | confs/confs.py L206-217 |
Python 标准库行为,建议文档中说明或统一转为小写处理 |
| P3-6 | 错误消息暴露底层 IO 异常信息 | confs/confs.py L144 |
Permission denied 等底层错误信息被原样返回给调用方 |
四、安全机制总结
| 机制 | 状态 | 说明 |
|---|---|---|
| 扩展名白名单 | ✅ | 仅允许 .ini/.conf/.cfg/.json/.yaml/.yml/.toml/.txt |
| 路径遍历防护 | ✅ | basename 校验 + realpath 前缀校验 |
| TOCTOU 防护 | ✅ | 文件系统操作(realpath→stat→open)全部在锁内原子完成 |
| 文件大小限制 | ✅ | 单文件上限 1 MiB(MAX_CONFIG_SIZE) |
| Slowloris 防护 | ✅ | pymsg MsgServer 默认 10 秒 recv 超时 |
| 缓存一致性 | ✅ | 所有公开方法持锁操作 |
| 缓存防污染 | ✅ | get() 返回浅拷贝,调用方修改不影响缓存 |
| list() 符号链接防护 | ✅ | realpath 解析后校验前缀,逃逸链接跳过 |
| 参数类型校验 | ✅ | name/key 非字符串或空值明确报错,不产生误行为 |
| 异常隔离 | ✅ | handler 异常由 RpcServer 包装为 success=false,不崩溃服务 |
| ConfigParser 安全 | ✅ | interpolation=None 禁用 %(key)s 插值,裸 % 不报错 |
| 仅监听本机 | ✅ | 默认 127.0.0.1 |
| 日志注入防护 | ❌ | 配置名/key 未过滤控制字符(P2-3) |
| 鉴权 | ❌ | 无身份校验,依赖"仅本机"信任边界 |
五、修复优先级建议
- 全部 P0/P1 已修复:共修复 1 个 P0 + 7 个 P1 问题(含此前修复的 pymsg/log_client/TOCTOU/OOM 等)
- 近期修复(P2): P2-3(日志注入,过滤控制字符)
- 可接受(P2-4/P3): 实际风险极低或属于运维/部署优化项