fimskiy/Evil-merge-detector

GitHub: fimskiy/Evil-merge-detector

检测 Git 仓库中绕过代码审查的邪恶合并提交,帮助发现供应链攻击中通过合并夹带的隐蔽代码改动。

Stars: 5 | Forks: 0

# Evil Merge Detector [![CI](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/2548bc73e7225803.svg)](https://github.com/fimskiy/Evil-merge-detector/actions/workflows/ci.yml) [![Go Report Card](https://goreportcard.com/badge/github.com/fimskiy/evil-merge-detector)](https://goreportcard.com/report/github.com/fimskiy/evil-merge-detector) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) [![Buy Me a Coffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-donate-FFDD00?logo=buymeacoffee&logoColor=black)](https://www.buymeacoffee.com/fimskiy) 检测 Git 仓库中的 **evil merge** —— 即# Evil Merge Detector [![CI](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/2548bc73e7225803.svg)](https://github.com/fimskiy/Evil-merge-detector/actions/workflows/ci.yml) [![Go Report Card](https://goreportcard.com/badge/github.com/fimskiy/evil-merge-detector)](https://goreportcard.com/report/github.com/fimskiy/evil-merge-detector) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) [![Buy Me a Coffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-donate-FFDD00?logo=buymeacoffee&logoColor=black)](https://www.buymeacoffee.com/fimskiy) 检测 Git 仓库中的**邪恶合并** —— 即包含超出冲突解决方案之更改的合并提交,这些更改对代码审查是不可见的。 ## 什么是邪恶合并? 邪恶合并是指引入了在任一父分支中均不存在的更改的合并提交。这些更改: - **绕过代码审查** —— 审查者看到的是分支差异,而不是合并提交本身 - **难以追踪** —— `git blame` 会指向该合并,而不是某个有意义的提交 - **可能隐藏恶意代码** —— 一种常见的供应链攻击途径 ``` feature ──●──────────────────────●── main \ / ●── evil change ───● ← merge commit contains extra code / main ─────● ``` ## 安装 **Homebrew:** ``` brew install fimskiy/tap/evilmerge ``` **Go:** ``` go install github.com/fimskiy/evil-merge-detector/cmd/evilmerge@latest ``` **二进制文件:** 从 [Releases](https://github.com/fimskiy/Evil-merge-detector/releases) 下载 ## 使用方法 ``` # 扫描当前 repository evilmerge scan # 扫描特定路径 evilmerge scan /path/to/repo # 扫描特定 branch(自指定日期起) evilmerge scan --branch=main --since=2024-01-01 # 仅显示关键 findings evilmerge scan --severity=critical # 用于脚本编程的 JSON 输出 evilmerge scan --format=json # 如果发现任何 warnings 则以代码 1 退出(用于 CI) evilmerge scan --fail-on=warning # 详细检查特定 merge commit(含 line diffs) evilmerge scan --commit=a1b2c3d # 将扫描限制为 60 秒(适用于非常大的 repository) evilmerge scan --timeout=60s ``` **示例输出:** ``` Evil Merge Detector v0.1.9 Scanning repository: /path/to/repo (branch: main) Analyzed 142 merge commits, found 2 evil merges (in 340ms) SEVERITY COMMIT AUTHOR FILES ---------------------------------------------------------------------------------------------------------- CRITICAL a1b2c3d Merge branch 'feature/auth' dev@company.com config.py WARNING d4e5f6a Merge branch 'hotfix/payment' dev@company.com utils.js Re-run with --format=json for full details on each merge. ``` ## 严重级别 | 严重性 | 含义 | |----------|---------| | **CRITICAL** | 文件在两个分支中均未更改,但在合并中被修改;在合并中添加了新文件;敏感文件(`.env`、`auth`、`crypto` 等)发生更改 | | **WARNING** | 文件在一个分支中发生了更改,但合并结果与两个父分支均不同 | | **INFO** | 文件在两个分支中均发生了更改(冲突区域) —— 可能是合法的冲突解决,值得审查 | ## GitHub App 最简单的入门方式 —— 安装一次,组织中的每个 Pull Request 都会被自动扫描。无需更改工作流。 **[从 GitHub Marketplace 安装 →](https://github.com/marketplace/evil-merge-detector)** - 通过 GitHub Checks 在每个 PR 上自动扫描 - 结果直接显示在 Pull Request 中 - 首次安装时进行完整历史扫描 —— 可捕获过去的事件 - 可在 [evilmerge.dev/dashboard](https://evilmerge.dev/dashboard) 查看扫描历史 - 发现邪恶合并时提供 Slack / webhook 通知 **计划:** 免费(公共仓库,每月 50 次扫描) · 专业版 $7/月(私有仓库,无限扫描,仪表板) **状态徽章** —— 添加到您的 README 中: ``` ![Evil Merges](https://evilmerge.dev/badge/owner/repo) ``` 根据最新扫描结果显示 `passing`(绿色)或 `N found`(红色)。 ## GitHub Action 添加到您的工作流以自动检查 PR 是否存在邪恶合并: ``` name: Evil Merge Check on: pull_request: types: [opened, synchronize] jobs: check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: fimskiy/Evil-merge-detector@v1 with: fail-on: warning ``` ### Action 输入 | 输入 | 描述 | 默认值 | |-------|-------------|---------| | `fail-on` | 导致检查失败的最低严重级别(`info`/`warning`/`critical`) | `warning` | | `severity` | 报告的最低严重级别 | `info` | | `branch` | 要扫描的分支(默认从 PR 自动检测) | — | | `since` | 仅扫描此日期之后的合并 (YYYY-MM-DD) | — | | `version` | 要使用的 evilmerge 版本 | `latest` | | `upload-sarif` | 将 SARIF 结果上传到代码扫描 | `false` | ### Action 输出 | 输出 | 描述 | |--------|-------------| | `evil-merges-found` | 如果发现邪恶合并则为 `true` | | `evil-merge-count` | 发现的邪恶合并提交数量 | ### 结合 SARIF 上传 ``` - uses: fimskiy/Evil-merge-detector@v1 with: fail-on: warning upload-sarif: true ``` 扫描结果将显示在 **Security → Code scanning alerts** 中,包含严重级别、受影响文件和提交指纹。 ## 其他 CI 集成 开箱即用的模板位于 [`examples/`](examples/): | 平台 | 文件 | |----------|------| | GitLab CI | [`examples/gitlab-ci.yml`](examples/gitlab-ci.yml) | | Bitbucket Pipelines | [`examples/bitbucket-pipelines.yml`](examples/bitbucket-pipelines.yml) | | 自托管 Git (pre-receive hook) | [`examples/pre-receive`](examples/pre-receive) | ## CI/CD 集成(手动) 如果您倾向于直接安装二进制文件: ``` - name: Check for evil merges run: | go install github.com/fimskiy/evil-merge-detector/cmd/evilmerge@latest evilmerge scan --branch=main --fail-on=warning ``` ## 标志 | 标志 | 描述 | 默认值 | |------|-------------|---------| | `--branch` | 要扫描的分支 | 当前 HEAD | | `--since` | 扫描此日期之后的提交 (YYYY-MM-DD) | — | | `--until` | 扫描此日期之前的提交 (YYYY-MM-DD) | — | | `--since-tag` | 扫描此标签之后的提交 | — | | `--until-tag` | 扫描此标签之前的提交 | — | | `--severity` | 报告的最低严重级别:`info`、`warning`、`critical` | `info` | | `--limit` | 要分析的合并提交最大数量 | 无限制 | | `--format` | 输出格式:`text`、`json`、`sarif` | `text` | | `--fail-on` | 如果发现达到或超过指定严重级别的结果,则退出码为 1 | — | | `--commit` | 详细检查特定的合并提交 (哈希值) | — | | `--timeout` | 最大扫描持续时间,例如 `30s`、`5m` | 无限制 | | `--ignore-bots` | 跳过已知机器人(dependabot、renovate 等)的合并 | false | | `--exclude` | 排除匹配此 glob 模式的文件中的发现结果(可重复使用) | — | | `--include` | 仅报告匹配此 glob 模式的文件中的发现结果(可重复使用) | — | | `--output` | 将结果写入文件而非标准输出 | — | | `--workers` | 用于合并分析的并行 worker 数量 | 1 | | `--verbose` | 将每个已分析的提交打印到标准错误 | false | ## 配置 项目级别的默认值位于仓库根目录的 `.evilmerge.yml` 中。CLI 标志会覆盖文件中的值;`exclude`/`include` 模式是累加的。 ``` # .evilmerge.yml fail-on: warning ignore-bots: true exclude: - "*.lock" - "dist/**" include: - "src/**" output: results.sarif ``` ### 忽略列表 创建 `.evilmerge-ignore` 以永久将特定的提交或作者加入白名单: ``` # 以 # 开头的行是注释 # Commit hashes(7–40 个十六进制字符,支持短前缀) abc1234 deadbeef12345678 # Author names 或 emails legacy-bot@company.com Merge Bot ``` 任何类似于十六进制字符串(≥7 个字符)的内容将被视为提交哈希前缀;其他所有内容均被视为作者姓名或电子邮件。 ## 工作原理 对于每个具有父提交 **P1** 和 **P2** 的合并提交 **M**: 1. 找到合并基点 **B** = P1 和 P2 的共同祖先 2. 对于 M 中的每个文件,将其内容与 B、P1 和 P2 进行比较 3. 标记出所有 M 的内容无法用任一父提交解释的文件 ## 许可证 MIT —— 详见 [LICENSE](LICENSE)
标签:CI/CD安全, DevSecOps, DNS 解析, EVTX分析, Go语言, Llama, StruQ, 上游代理, 云安全监控, 仓库扫描, 代码安全, 代码审查, 代码篡改检测, 后门检测, 安全可观测性, 日志审计, 源代码管理, 漏洞枚举, 版本控制, 程序破解, 网络安全研究, 邪恶合并, 静态分析