1仕組みと動作原理
このSkill全体は「ワークフローのオーケストレーション(SKILL.md)+ 4本の実行可能Pythonスクリプト + 3件の参照ドキュメント」で構成されています。SKILL.mdは手順と制約事項のみを定義し、機械的な処理はすべてscripts/配下のスクリプトに委譲され、各スクリプトがsubprocess経由でgit、gitleaks、git-filter-repo、ghを呼び出します。
The bundled scripts automate the mechanical parts:
スキャンは4層構造で設計されています。Layer 1:gitleaks(シークレット/トークン)、Layer 2:カスタム正規表現(イントラネットIP、電話番号、リポジトリ固有のPII)、Layer 3:ユーザー独自のgitleaks設定から抽出された社内ドメイン/IPルール + 任意のidentitiesファイル、Layer 4:エージェントが手動で実施するAIセマンティックレビューです。スクリプト自身はLayer 1〜3のみを実行し、Layer 4は「手動確認が必要」というフラグ付けのみを行います。
Layer 4: AI semantic review flag (must be performed manually by an agent)
全履歴のスキャンはgitleaks単体には依存しません。カスタムレイヤーおよびLayer 3では、`git rev-list --all` で全コミットを取得し、分割バッチ(batch_size=500)で `git grep --perl-regexp` に渡して該当するコミットハッシュをバッチごとに収集します。これにより、コマンドライン長の上限を回避し、直近N件のコミットしかスキャンされない事態を防ぎます。
and to ensure the entire history is searched (not just the newest N).
プライベートルールを公開リポジトリに含めない設計:Layer 3はプライベートドメイン一覧をハードコードせず、実行時にユーザー独自のgitleaks TOMLから特定の2つのルールID(private-domain-context / private-ip-context)の正規表現のみを抽出し、さらに任意の行単位identitiesファイル(各行をre.escapeしてリテラルとして扱う)を読み込みます。
LAYER3_RULE_IDS = ["private-domain-context", "private-ip-context"]
履歴書き換え前の強制バックアップゲート:a) `git-filter-repo` がPATHに存在し実行可能であることの確認、b) ワーキングツリーがクリーンであることの確認(`git status --short` に出力があれば即座に中断)、c) `git bundle create --all` によるバックアップと直後の `git bundle verify` による検証を実施し、いずれかのステップが失敗した場合は書き換えを行わずに即時終了します。
raise RuntimeError(f"Backup verification failed: {verify.stderr}")
履歴書き換えの本体は `git-filter-repo --force --replace-text <file>` であり、コミットメッセージを対象とする `--replace-message <file>` の追加指定も可能です。これにより、blobのみを変更してコミットメッセージ内に機密識別子が残ってしまう問題(v1.1.0で修正)を防止します。
cmd += ["--replace-message", str(message_replacements_path)]
検証フェーズも2系統のアプローチを採用し、「2つの検査手法が同一の死角を共有する」障害パターンを防ぎます。blobチャネルでは全コミットに対して `git grep` を実行し、メッセージチャネルでは `git log --all --format=%H%x1f%B%x1e` を用いて各コミットメッセージを抽出・マッチングします。不合格時には単なる件数ではなく該当するコミットハッシュ(上位10件)を出力します。
"--format=%H%x1f%B%x1e", "--no-color"],
プッシュ処理はフェイルクローズ(安全側に倒す)のゲートを設けています。まず `gh repo view --json visibility,isPrivate,stargazerCount,forkCount,owner,name` を実行し、作業ディレクトリからリポジトリを判定します(owner/repo文字列の推測は行いません)。ghコマンドの失敗やキーの欠落がある場合は推測を行わずに即時中断します。公開リポジトリかつ `forkCount > 0` の場合は警告を出力し、`--yes` の指定がなければ終了します。プッシュはまず `--force-with-lease` を試行し、標準エラー出力に stale info が確認された場合に限り1回のみ `--force` へのフォールバックを許可します。
if "stale info" in result.stderr.lower():
2コア機能
3外部依存関係
| Kind | Dependency / Endpoint |
|---|---|
| cli | gitleaks(Layer 1 密钥扫描) |
| cli | gitleaks detect(子进程实参:--source / --report-format json / --report-path / --verbose) |
| cli | git-filter-repo(历史重写,须在 PATH 且 --version 可执行) |
| cli | git(bundle create --all / bundle verify / status --short / show-ref --heads / rev-list --all / grep --perl-regexp / log --all / push --force-with-lease|--force) |
| cli | gh(GitHub CLI,用于仓库可见性与 fork 数核查) |
| api | GitHub REST API(由 gh repo view 隐式访问;源码内无字面 URL,端点归属 GitHub) |
| network | PyPI(文档命令 `uv run --with gitpython ...` 会要求 uv 从包索引获取 gitpython;四个脚本实际零 gitpython import,属文档声明依赖——[INFERENCE] 端点归属,源码内无 URL) |
| package | gitpython(SKILL.md 与四个脚本 docstring 的命令示例中声明;代码无 import,属未使用的声明依赖) |
| cli | uv(文档规定的运行器:uv run --with gitpython / uv run scripts/...) |
| cli | date(取 UTC 时间戳写入报告 scanned_at) |
| cli | brew(仅安装说明:git-filter-repo / gitleaks / gh) |
| cli | BFG Repo-Cleaner(参考文档里的备选工具,需 Java;未被脚本调用) |
| network | 用户侧的私有规则/身份清单文件(非网络端点,但属外部运行时输入):私有 gitleaks.toml、identities.txt、repo 根 .pii-patterns |
4推奨統制措置と判定根拠
- scripts/: ローカルスクリプト・コマンドの実行: `scripts/scan_repo.py` において `shutil.which("gitleaks")` を実行後、`subprocess` 経由で `gitleaks detect` を呼び出します。
- 网络端点: 外部ネットワークアクセスの宣言: `safe_push.py` が `gh` CLIを介してGitHub REST API(`api.github.com`)にアクセスし、リポジトリの `visibility` や `isPrivate` などのメタデータを取得します。
- 本地工作目录: ファイル読み書きおよび成果物の出力: `scan_repo.py` は `--output` で指定されたJSONレポートを出力し(親ディレクトリを自動生成)、gitleaksの一時レポートファイルを作成・削除します。
5二重目の独立検証
- [ok] 文件清单全量核对(有无未列出的隐藏脚本/数据文件) — glob(hidden=true, gitignore=false)结果仅 9 个文件:SKILL.md、evals/evals.json、references/{ai_semantic_review_prompt,incident-lessons,tooling_notes}.md、scripts/{rewrite_history,safe_push,scan_repo,verify_cleanup}.py。无隐藏文件、无二进制、无 .pii-patterns 样本、无内置 hook;仓库级的 PII Guard hook(~/scripts/git-pii-guard)与 .githooks/ 属仓库/机器环境,不在 skill 目录内,skill 只是要求不得绕过它。
- [ok] external_deps 逐条反查调用点 — 全部命中:gitleaks → scan_repo.py `gitleaks_bin = shutil.which("gitleaks")` + verify_cleanup.py 同名调用;git-filter-repo → rewrite_history.py `shutil.which("git-filter-repo")` 且随后 `--version` 探测;git → show-ref/status/bundle create/bundle verify/rev-list/grep/log/push 各自 subprocess.run 均可定位;gh → safe_push.py 的 `["gh", "repo", "view", "--json", ...]`;date → scan_repo.py `["date", "-u", "+%Y-%m-%dT%H:%M:%SZ"]`;uv/brew 只出现在文档命令与 Prerequisites,无对应代码调用(已在条目 note 中说明)。
- [ok] 安全结论反例搜索:是否存在漏掉的网络调用、隐藏外发或混淆内容 — 未找到反例,安全结论成立(记录检索范围以免过度外推):对 skill 目录 grep `requests|urllib|socket|curl|wget|http://|https://` 零命中,且全目录无任何 http(s):// 字面 URL(连「联系 GitHub Support」一段也只用文字);无 base64/fromhex/codecs/eval/exec/__import__ 等混淆或动态执行构造,无 60 字符以上的不透明长 token;对 git / git-filter-repo / gitleaks / gh / date 之外的二进制调用为零。唯一出网路径是 safe_push.py 经 gh 访问 api.github.com(uv --with gitpython 的包索引访问属 uv 行为而非脚本行为,已在 external_deps 标注 [INFERENCE] 端点)。证明边界:这是对该 commit 下 9 个文件的静态核对,不含运行时行为。
- [ok] 实现原理是否夸大:SKILL.md「What the Bundled Scripts Do」逐条对代码 — 四条声明全部落地:scan_repo.py 确实同跑 gitleaks 与自定义 grep 层并输出 JSON;rewrite_history.py 确实先备份再 `git filter-repo --replace-text`,且 `--message-replacements` 确实映射到 `--replace-message`;verify_cleanup.py 确实同时查 blob(git grep 全 commit)与 commit message(`git log --all --format=%H%x1f%B%x1e`),使漏改 message 的重写必然失败;safe_push.py 确实调 gh repo view 并走 lease-first。SKILL.md 未出现代码做不到的承诺。
- [ok] 7 条不可协商安全规则在 SKILL.md 的位置与代码落地情况 — SKILL.md 第 64~77 行「Safety Rules (Non-Negotiable)」编号 1~7:scan-before-decide / backup-before-rewrite / gh repo view 验可见性且不得从 URL 或目录名推断 / 绝不 --no-verify / --force-with-lease 优先且仅在 remote ref stale 时回退 --force / 重写后必须重新扫描 + AI 语义审查 / 公开且带 forks 需格外小心。落地核对:规则 2、4、5 有代码门禁(备份+verify、脚本从不加 --no-verify、lease→stale info→force 一次);规则 3 有硬门禁(gh 失败或元数据缺 key 即 abort);规则 1、6、7 依赖 agent 遵守文档与人工动作(scan 结果、--yes、fork 通知),不由代码强制——这是规则与实现的唯一不对称处。
- [ok] safe_push.py 的 public+forks 判定与 force-with-lease 回退条件 — 判定式为 `if not info["isPrivate"] and info["forkCount"] > 0:`,命中时只向 stderr 打印 `WARNING: This is a PUBLIC repository with {forkCount} forks.`,不阻断流程;唯一的硬门禁是缺 --yes 时 exit(1)。回退条件为 `if "stale info" in result.stderr.lower():`(对应 git 对 force-with-lease 拒绝时的 (stale info) 文案),回退仅一次 (--force),再失败即 exit(1)。注意:脚本不校验 remote/branch 是否与默认分支一致,也不在回退前复跑验证——--repo/--remote/--branch 参数的正确性由操作者负责。
- [discrepancy] 文档声明的依赖 gitpython 是否真实被使用 — 四处 docstring 与 SKILL.md 多处命令写 `uv run --with gitpython scripts/...`,但四个脚本的 import 块逐行核对后只有 argparse/json/re/shutil/subprocess/sys/tempfile/tomllib/pathlib,零 `import gitpython` 或 `from git import`。即文档要求 uv 从包索引拉一个不使用的第三方包(多余供应链接触面),去掉 `--with gitpython` 不影响任何功能;此外同一份 SKILL.md 内部不一致:Step 4/5/6 的命令写 `uv run scripts/...`(不带 --with),Step 1/1.5 与「What the Bundled Scripts Do」写 `uv run --with gitpython`。
- [discrepancy] --gitleaks-config 是否被传给 gitleaks 本体 — run_gitleaks 的 cmd 只有 `detect --source --report-format --report-path --verbose`,没有 `--config`;用户私有 gitleaks.toml 仅被 parse_gitleaks_rules 解析出 private-domain-context / private-ip-context 两条 regex 供 Layer 3 的 git grep 使用。SKILL.md 的说法(该 flag 用于从私有配置读取这两条规则)与代码一致,不存在夸大;但若用户以为私有配置会整体驱动 gitleaks 扫描(例如自定义 allowlist/其它私有规则),实际不会——gitleaks 走自身默认配置与仓库本地 .gitleaks.toml。此项为「文档未声明但易误读」的行为差异,非虚假声明。
6結論
aa1ae4b1f420e74a…