Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions lessons/dco-check-hook-audit-comparison.md
Original file line number Diff line number Diff line change
@@ -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 自动修复工作流
Loading