跳转至

审计报告自审计 — AUDIT_REPORT_20260406_FULL.md

审计对象docs/AUDIT_REPORT_20260406_FULL.md 审计时间:2026-04-06 方法:逐条对照源代码验证报告中的每一条事实声明


总评

报告整体质量中等偏上。事实核查基本准确,修复状态更新及时。但存在以下系统性问题:

维度 评分 说明
事实准确性 7/10 6 处过时/错误
行号引用 4/10 大量行号已过时,未随修复更新
严重性判定 8/10 基本合理,一处分级有争议
完整性 5/10 漏掉 4 个值得审计的问题
结构一致性 6/10 "修复后"评分与正文矛盾

一、事实错误(6 处)

错误 1:行号引用全部过时

位置:报告全文,至少 8 处行号引用

报告中的引用 报告声称的行号 实际行号(修复后) 偏差
contacts_tracker.py TOCTOU 代码示例 §3.1 L82-90 update() 现在在 L163-220 +30 行
contacts_tracker.py:128 SQL 拼接 §3.2 实际在 L142 +14
contacts_tracker.py:196 SQL 拼接 §3.2 实际在 L215 +19
contacts_tracker.py:149-199 update 函数 §4.1 实际在 L163-220 +14 到 +21
metrics.py:82-95 fetch_repo §2.3 实际在 L92-111 +10 到 +16
metrics.py:98-135 collect_metrics §4.2 实际在 L114-151 +16
metrics.py:190-222 format 函数 §4.3 实际在 L206-238 +16
metrics.py:20-27 REPOS 字典 §4.4 ✅ 正确,未变 0
contacts_tracker.py:74-75 _row_to_contact §3.4 实际在 L85-86 +11
contacts_tracker.py:257-282 import_targets_md §2.4 实际在 L278-312 +21 到 +30

根因:报告先写修复前代码,后做修复,但未同步更新行号。这是审计报告最严重的质量问题——行号对不上会让后续开发者按图索骥时产生困惑,降低报告的可信度。

错误 2:§2.1 明文写出了 npm token 明文

位置:报告 L29

**内容**:`//registry.npmjs.org/:_authToken=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`

问题:审计报告的目的是指出安全风险,而不是复现安全风险。将完整 token 明文写入审计报告 = 审计报告本身成了泄露载体。如果这份报告被提交到 git(它是未被追踪的 docs/ 文件,但可能被 git add . 误加),token 就进入版本历史了。

应该:只写 npm_<前4位>...<后4位>npm_gW...pq(脱敏处理)。

错误 3:§2.2 权限声称已过时

位置:报告 L41

**权限**:`644 (ai:ai)` — 所有用户可读

实际:权限已修复为 600。但报告第二节的正文仍然描述旧状态 644,只在第七节修复表中标注了 "✅ 已修复"。读者只看第二节会得到错误印象

应该:在 §2.2 正文中添加 (已修复为 600) 的标注,或使用删除线标记旧值。

错误 4:§2.4 解析器行号和描述均过时

位置:报告 L59

**文件**:`src/contacts_tracker.py:257-282`

实际:修复后函数在 L278-312。同时报告正文描述的是修复的行为("只看 - **xxx** 格式,不验证内容"),但代码已经添加了 _TABLE_HEADERS 过滤、长度检查、空名称检查。读者会以为这个 bug 还存在

错误 5:§3.3 描述了已修复的问题但未标注

位置:报告 L113-114

- `add()` 不校验参数(空名称、超长字符串)
- `update()` 不校验 status 是否在枚举范围内

实际add() 现在有空名称检查和 200 字符截断(L100-102);update() 现在有 VALID_STATUSES 枚举校验(L173-175)。这两条已不成立。

错误 6:§6.1 __pycache__ 描述不准确

位置:报告 L233

- `src/__pycache__/` 在 git 追踪中(不应提交)

实际src/__pycache__/ 从未被 git 追踪。git ls-files src/__pycache__/ 返回空。.gitignore 中已有 __pycache__/ 规则。这条在 P1 修复表中已更正为"✅ 不需要",但 §6.1 正文仍写"在 git 追踪中",事实矛盾


二、遗漏问题(4 处)

遗漏 1:_db_initialized 的进程内全局变量问题

文件contacts_tracker.py:44metrics.py:49

_db_initialized = False  # 模块级全局变量

修复 P1 #9 引入了 _db_initialized 标志来避免重复 CREATE TABLE。但这引入了新问题

  • 如果数据库文件被手动删除后重新创建,_db_initialized 仍为 True,后续连接不会执行 CREATE TABLE → 所有操作报 no such table 错误
  • 该标志是进程内的,重启 Python 进程后重置为 False,所以实际上 CREATE TABLE 仍然会在每次进程启动的第一次调用时执行——性能收益仅限于同一进程内的第二次及后续调用,对于 CLI 场景(每次命令一个进程)几乎无意义
  • PRAGMA journal_mode=WAL 同理,每次进程启动仍会执行

审计报告声称的性能问题"浪费"(§3.1)被夸大了——对于 SQLite,CREATE TABLE IF NOT EXISTS 在表已存在时是极快的元数据检查(微秒级)。真正的"浪费"是打开连接的开销,而这个问题并未被修复。

遗漏 2:_LINE_PATTERNS 定义了但从未使用

文件contacts_tracker.py:285

_LINE_PATTERNS = {"邀请", "讨论", "联系", "发布", "分享", "关注", "建议", "观察"}

这个集合被创建但从未在 import_targets_md() 中引用。报告 §2.4 说修复了解析器,但实际上遗漏了一个本应使用的过滤机制。这是一个死代码问题,也意味着报告声称的修复不完全——包含"邀请相关领域大V讨论"这样的操作建议文本理论上仍然能通过(只要它匹配 - **xxx** 格式且不在 _TABLE_HEADERS 中)。

遗漏 3:os.chmod() 每次调用都执行

文件contacts_tracker.py:74-77metrics.py:77-80

try:
    os.chmod(str(DB_PATH), 0o600)
except OSError:
    pass

修复 P0 #2 在 _get_db() 中添加了 os.chmod()。但这意味着每次数据库操作都执行一次 chmod 系统调用。对于频繁调用(如 import_targets_md() 导入 20 个联系人 = 60 次 chmod),这是不必要的 I/O。正确做法是在数据库创建时执行一次,或检查当前权限后再决定是否修改。

遗漏 4:docstring 中的 Usage 示例是错误的

文件contacts_tracker.py:5-12

"""
Usage:
    from contacts_tracker import ContactsTracker
    tracker = ContactsTracker()
    tracker.add("Hacker News", "Show HN", channel="hn", priority="P0")
"""

问题:代码中不存在 ContactsTracker 类。所有函数都是模块级函数。这个 docstring 示例会导致 ImportErrorAttributeError。审计报告 §3.5 提到"无测试",但没有注意到 docstring 中的代码示例本身就是错的——如果有人尝试按文档使用,会立刻失败。


三、严重性判定争议(1 处)

§2.3 GitHub API 无 Token — 不应归为 P0

报告将此放在"二、安全问题(P0)"章节中,标题为"GitHub API 无 Token — 信息泄露反向风险"。但报告自己的描述承认"不是泄露风险,而是可靠性风险"。

P0 应该是"安全 + 数据完整性"。速率限制问题: - 不涉及安全漏洞 - 不涉及数据损坏 - 最坏情况是采集数据缺失(静默返回 None)

这应该是 P1 或 P2 级别。放在 P0 章节拉低了 P0 的严肃性。


四、结构问题(3 处)

结构问题 1:修复前后状态混在同一份报告中

报告同时包含"修复前的问题描述"和"修复后的状态更新",但没有用删除线或版本标记区分。读者无法区分哪些描述是历史状态、哪些是当前状态。

建议做法: - 在每个已修复的问题标题后加 (✅ 已修复) - 或将修复状态统一移到 §七,§二~§六保持原始审计快照不动

结构问题 2:§七 P2 表格格式不完整

报告 L281-283:

|| 12 | 添加 CLI 入口点 | 2h | 可用性 |
|| 13 | 添加基本测试 | 3h | 回归保护 |
|| 14 | 标记/归档未审核的发布文件 | 30min | 防止误发有问题的内容 |

缺少"状态"列(P0/P1 表格有,P2 没有),且 #14 与 P1 #7 功能重复。

结构问题 3:§一评分表用了箭头符号但不一致

|| 安全 | **2/10** → **6/10** | 🟡→🟢 修复后 |
|| 架构 | **4/10** | 🟡 早期阶段 |

有些维度有修复前后对比,有些没有。"内容真实性"评了 7/10 但没有箭头,暗示没变,但旧文件现在已标记 UNREVIEWED——这算不算改进?评分逻辑不透明。


五、修复质量评价

对报告声称"✅ 已修复"的 9 个项目逐一验证:

# 问题 报告声称 实际验证 质量评价
P0 #2 DB 权限 ✅ chmod 600 + 自动修复 权限确实是 600 ⚠️ 自动修复每次调用都 chmod,有性能开销
P0 #3 解析器 ✅ 过滤表头、短名称、空名称 过滤确实生效 ⚠️ _LINE_PATTERNS 未使用,操作建议文本仍可通过
P0 #4 TOCTOU ✅ 单连接读+写 确实只用一个连接 ✅ 修复质量好
P1 #7 UNREVIEWED 标记 ✅ 3 个文件添加 HTML 注释 标记确实存在 ✅ 够用
P1 #8 GitHub Token ✅ 支持 GITHUB_TOKEN 环境变量 确实支持 ✅ 修复质量好
P1 #9 _get_db 优化 ✅ _db_initialized 标志 确实加了 ⚠️ 仅进程内有效,CLI 场景无收益
P1 #10 LICENSE ✅ MIT License 文件存在 ✅ 正确
P1 #5 pycache ✅ 不需要(未被追踪) 确实未被追踪 ✅ 判定正确
P1 #6 .gitignore ✅ 已存在 确实存在 ✅ 正确

修复合格率:6/9 完全合格,3/9 有瑕疵但可用。


六、一句话总结

审计报告的事实基底正确,但自审失败——报告描述的是修复前的代码快照,却没有标注"这是历史状态"。 6 处行号过时、4 处遗漏、npm token 明文写入报告本身。建议:要么将报告拆为"审计快照"和"修复状态"两份文档,要么在每个已修复的问题标题加 (✅ 已修复) 并标注实际行号。


自审计人:灵扬 LingYang (Crush GLM-5.1)