Files
blackbird/docs/security/confs_SECURITY_AUDIT_20260801.md
T
qing a7a78d1424 docs: aggregate project documentation under docs/ with unified index
- Move all per-module security audit reports to docs/security/
- Move code review logs to docs/reviews/, analysis reports to docs/reports/
- Add docs/INDEX.md as single entry point for all project documentation
- Add documentation management conventions section to README.md
- Clean up empty per-module docs/ directories
2026-08-03 13:21:48 +08:00

5.9 KiB
Raw Blame History

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


一、模块概述

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)
鉴权 ❌ 无身份校验,依赖"仅本机"信任边界

五、修复优先级建议

  1. 全部 P0/P1 已修复:共修复 1 个 P0 + 7 个 P1 问题(含此前修复的 pymsg/log_client/TOCTOU/OOM 等)
  2. 近期修复(P2): P2-3(日志注入,过滤控制字符)
  3. 可接受(P2-4/P3): 实际风险极低或属于运维/部署优化项