Files
daymade 776b760c10 fix(github-sensitive-data-cleanup): 关闭 git 输出解码崩溃类 + 文档精确化(审阅轮 2) (#330)
代码(审阅 HIGH,已实跑复现):
- 全部 4 个脚本的 13 处 subprocess text=True 解码统一补 errors="replace"
  ——blob 通道(git grep, grep_all_commits)至今 strict 解码,GBK 编码
  源文件含命中行时 verify/scan 照样 UnicodeDecodeError 崩掉无报告;
  Lesson 9 的处方此前只落在 message 通道,现对该类整体闭环
- 验证:GBK 源文件含泄漏 → FAILED 且 blob+message 双通道各自定位
  commit hash(此前崩溃点);scan_repo 同仓 exit 0;GBK message 不崩

文档(审阅 LOW×2 + INFO×1):
- tooling_notes/SKILL.md/Lesson 7 的 git log 字面命令与实际
  --format=%H%x1f%B%x1e 不符,改为行为描述(hash 标注记录格式)
- tooling_notes/Lesson 9/CHANGELOG 补 commit_message_commits 前 10 截断说明
- CHANGELOG 修正 #328 的 --yes 修复面(Step 4 两块 + reference 节一块)
- Lesson 9 补记 blob 通道同类缺陷的发现与闭环 + 跨编码检测边界
  (errors=replace 防崩不让 UTF-8 pattern 命中 GBK 字节,归 Layer 4)

Co-authored-by: Claude <noreply@anthropic.com>
2026-08-23 12:21:35 +08:00

3.2 KiB

Tooling Notes for GitHub Sensitive Data Cleanup

git-filter-repo vs BFG Repo-Cleaner

  • Pros: Modern, actively maintained, Python-based, flexible --replace-text, readable docs, safer defaults than git-filter-branch.
  • Cons: Requires a "fresh enough" clone (no multiple remotes, no stale refs). Slower than BFG on very large repositories.
  • Install: brew install git-filter-repo

BFG Repo-Cleaner

  • Pros: Very fast on large repos. Good for removing large files or converting files to git-lfs.
  • Cons: Requires Java. Less flexible than git-filter-repo for arbitrary string replacement. Slightly more complex for private-domain replacement.
  • Install: Download the JAR from the official repo.

Rule of thumb: Use git-filter-repo for private-domain / secret-string replacement. Use BFG if the repo is huge and you are mainly removing large files.

Common git-filter-repo Errors

"Need a fresh clone"

Error: Need a fresh clone to operate on.  Please clone with `git clone --mirror ...`

Cause: The repo has multiple remotes, stale refs, or was not cloned normally.

Fix:

git clone --mirror /path/to/repo /tmp/repo-mirror.git
cd /tmp/repo-mirror.git
# run rewrite_history.py here

"Cannot combine --force with ..."

git-filter-repo has strict option validation. Read the error and adjust the command. The bundled rewrite_history.py uses the minimal safe set of flags.

gitleaks Allowlist Patterns

If gitleaks flags test fixtures or documentation examples, add an allowlist rather than bypassing the hook.

Example .gitleaks.toml:

title = "Repo allowlist"

[allowlist]
paths = [
  '''tests/fixtures/secrets.json''',
  '''docs/examples.md''',
]
regexes = [
  '''sk-kimi-REDACTED''',
]

Never use --no-verify to suppress a real finding.

Replacement File Syntax

git-filter-repo --replace-text accepts a file with one replacement per line:

literal:old-string==>new-string
regex:old-pattern==>new-string

Use literal: for exact strings. Use regex: only when necessary and test thoroughly, because a bad regex can corrupt many commits.

Checking Whether a String Is in History

git log --all --pickaxe-regex -S 'your-pattern' --pretty=format:'%H %s'

Use this pickaxe form for a manual "when did this string enter/leave" check. verify_cleanup.py itself checks each pattern over both channels: blob content (git grep across every commit's tree) and commit messages (git log over all refs with a hash-annotated record format, decoded with errors="replace" so legacy-encoded messages cannot crash verification). A FAILED message check lists the offending commit hashes (commit_message_commits, first 10), not just a count.

Git Bundle Backups

A bundle is a file that contains a complete copy of the repository refs. It can be cloned or fetched from later:

# Create
git bundle create backup.bundle --all

# Verify
git bundle verify backup.bundle

# Restore
git clone backup.bundle restored-repo

GitHub Support

For severe leaks (live production secrets, PII), contact GitHub Support after rotating credentials. They can remove cached views of sensitive data and assist with repository-level cleanup.