diff --git a/lessons/dco-check-hook-audit-comparison.md b/lessons/dco-check-hook-audit-comparison.md new file mode 100644 index 00000000..6366fdd6 --- /dev/null +++ b/lessons/dco-check-hook-audit-comparison.md @@ -0,0 +1,99 @@ +--- +{"title": "DCO 校验钩子对抗审计 — 三种方案极限测试与选型建议", "domain": "devops", "tags": ["dco", "signed-off-by", "pre-commit", "quality-gate", "audit", "对抗测试", "pygrep"], "status": "published", "source": "gleam", "created": "2026-06-14 00:00:00 UTC", "updated": "2026-06-14 00:00:00 UTC"} +--- + +## 背景 + +MisakaNet 的 DCO(Developer Certificate of Origin)质量门使用自研的 `pre-commit-dco` 钩子。此前开发者向官方 `pre-commit-hooks` 提交 PR #1262 贡献原生 check-dco 钩子,但被维护者以"可以通过 pygrep 实现,无需编写代码"为由拒绝。 + +我们需要回答一个核心问题:**官方维护者的"pygrep 替代论"在技术上是否成立?自研 DCO 钩子是否必要?** + +## 测试方案 + +对三种 DCO 校验方案进行极限对比测试: + +| 方案 | 来源 | 实现方式 | +|------|------|----------| +| 方案 A | 官方推荐 | pygrep 原生正则 `grep -E '^Signed-off-by:'` | +| 方案 B | PR #1262 | Python re + argparse 精细化解析 | +| 方案 C | MisakaNet 自研 | Ikalus1988/pre-commit-dco | + +### 测试用例设计 + +共 17 个测试用例,覆盖 4 大类: + +1. **正常用例**(2个):标准单签名、标准多签名 +2. **边界用例**(10个): + - 一行多个 Signed-off-by + - 非标准邮箱格式(无尖括号、+标签、无@符号) + - 没有空行分隔的签名 + - Unicode/特殊字符姓名 + - 空提交信息 +3. **欺骗用例**(2个):正文中出现关键词、缩进伪装 +4. **争议用例**(3个):大小写敏感、尾部空白、姓名含尖括号 + +## 测试结果 + +### 核心指标 + +| 方案 | 准确率 | 精准率 | 召回率 | 误报率 | 漏报率 | +|------|--------|--------|--------|--------|--------| +| 方案A (pygrep) | **76.5%** | 69.2% | 100.0% | **50.0%** | 0.0% | +| 方案B (PR#1262) | **94.1%** | 90.0% | 100.0% | 12.5% | 0.0% | +| 方案C (自研) | **76.5%** | 72.7% | 88.9% | 37.5% | 11.1% | + +### 关键发现 + +#### 1. "pygrep 替代论"不成立 + +pygrep 误报率高达 **50%**,意味着每两个不合规签名就有一个会被放过。它只检查行首字符串,完全不校验格式。对于 DCO 这种具有法律意义的合规检查,50% 误报率是不可接受的。 + +**结论:自研 DCO 钩子在方向上是正确的。** + +#### 2. 自研实现有已知缺陷 + +当前自研方案准确率仅 76.5%,与 pygrep 处于同一水平。存在 4 个已知缺陷: + +| # | 缺陷 | 类型 | 严重程度 | +|---|------|------|----------| +| 1 | 一行多个签名被误判为有效 | 误报 | 高 | +| 2 | 邮箱缺少 @ 仍通过 | 误报 | 中 | +| 3 | 尾部空白导致匹配失败 | 漏报 | 中 | +| 4 | 姓名含尖括号解析错误 | 误报 | 低 | + +**根因**:使用 `re.MULTILINE` + `findall` + 非贪婪匹配,在复杂场景下正则回溯导致错误解析。 + +#### 3. PR #1262 方案质量更高 + +反直觉的是,被官方拒绝的 PR #1262 反而是三个方案中准确率最高的(94.1%),只有 1 个已知缺陷(邮箱无@)。 + +它采用**逐行匹配 + malformed 检测**的设计,架构更清晰,错误提示更友好。 + +## 修复建议 + +### 立即修复(高优先级) + +1. **尾部空白问题**:将 `>$` 改为 `>\s*$` +2. **邮箱 @ 校验**:邮箱正则增加 `@` 验证 +3. **一行多签名问题**:改用逐行匹配而非 MULTILINE findall + +### 长期改进 + +1. 参考 PR #1262 的逐行匹配 + malformed 检测架构重构 +2. 补充单元测试,覆盖全部 5 类边界 case +3. CI 中接入 DCO 校验回归测试 + +## 验证 + +使用对抗测试脚本重新跑 17 个用例,准确率应 ≥ 90%。 + +```bash +# 运行对抗测试 +python3 scripts/test_dco_audit.py +``` + +## 关联 + +- 配套工作流:`dco-check.yml` + `fix-dco.yml` +- 协议配置:`misaka-protocol.json` → `dco` 段 +- 相关 lesson:DCO 自动修复工作流