ホーム / 全スキル / ワークフロー&基本ツール / github-sensitive-data-cleanup
ワークフロー&基本ツール · daymade/claude-code-skills

github-sensitive-data-cleanup

GitHubリポジトリのコミット履歴から機密データ(シークレット、APIキー、内部ドメイン/IPアドレス、個人情報)をスキャンして削除します。「scan sensitive data」「clean git history」「remove secrets from repo」「sanitize GitHub history」「清理敏感数据(機密データのクリーンアップ)」「历史重写(履歴の書き換え)」「force push」「泄露(漏洩)」などの指示を受けた際、または公開リポジトリへ誤ってシークレットや内部情報を漏洩させた後の復旧作業で使用します。また、公開リポジトリへのforce push前に、公開範囲、バックアップ、スキャン結果の検証を行う際にも使用します。

L4 高権限 · 段階的認可と監査V1 コミット固定コマンド実行ネットワーク通信ファイル書き込みDual-pass Audit
Author daymadeGitHub daymade/claude-code-skills ↗Stars 1385License MIT(仓库根 LICENSE 文件;GitHub API spdx MIT;Copyright (c) 2025 daymade)Commit d5c4678cb5
管理レベルは Skill の能力と推奨統制措置を示すものであり、品質や安全性の認証、利用可否の判定ではありません。使用の可否はユーザーおよび管理者が決定します。Agent 環境によって制約が異なるため、自動保護を仮定しないでください。第三者製 Skill の著作権は原著作者に帰属し、利用リスクは利用者が負います。

1仕組みと動作原理

このSkill全体は「ワークフローのオーケストレーション(SKILL.md)+ 4本の実行可能Pythonスクリプト + 3件の参照ドキュメント」で構成されています。SKILL.mdは手順と制約事項のみを定義し、機械的な処理はすべてscripts/配下のスクリプトに委譲され、各スクリプトがsubprocess経由でgit、gitleaks、git-filter-repo、ghを呼び出します。

github-sensitive-data-cleanup/SKILL.md
The bundled scripts automate the mechanical parts:
動作の仕組み:SKILL.md自体にはシェルの実行ロジックは一切含まれず、エージェントは「Step 0〜7 + 7つの厳格な安全規則」を解釈します。実際の実行主体は4つの独立したCLIスクリプトであり、このSkillの機能上限はプロンプトの表現ではなくこれらスクリプトの仕様に準拠します。

スキャンは4層構造で設計されています。Layer 1:gitleaks(シークレット/トークン)、Layer 2:カスタム正規表現(イントラネットIP、電話番号、リポジトリ固有のPII)、Layer 3:ユーザー独自のgitleaks設定から抽出された社内ドメイン/IPルール + 任意のidentitiesファイル、Layer 4:エージェントが手動で実施するAIセマンティックレビューです。スクリプト自身はLayer 1〜3のみを実行し、Layer 4は「手動確認が必要」というフラグ付けのみを行います。

github-sensitive-data-cleanup/scripts/scan_repo.py
Layer 4: AI semantic review flag (must be performed manually by an agent)
ファイル冒頭のdocstringに明記されています。重要な設計方針:正規表現レイヤーでは事前に定義されていない私的コンテキスト(本名、プロジェクトのコードネーム、会話の文字起こし断片など)を検知できないため、スクリプト側ではレポート辞書内の `ai_semantic_review_required: True` を通じてモデルや人間にレビューを委ねる仕様となっています。

全履歴のスキャンはgitleaks単体には依存しません。カスタムレイヤーおよびLayer 3では、`git rev-list --all` で全コミットを取得し、分割バッチ(batch_size=500)で `git grep --perl-regexp` に渡して該当するコミットハッシュをバッチごとに収集します。これにより、コマンドライン長の上限を回避し、直近N件のコミットしかスキャンされない事態を防ぎます。

github-sensitive-data-cleanup/scripts/scan_repo.py
and to ensure the entire history is searched (not just the newest N).
実装の詳細:`grep_all_commits()` 内部では、各パターンに対して `git grep -n --perl-regexp -e <pattern> <batch...>` を実行します。returncodeが1かつ標準出力が空の場合は該当なしと判定され(エラーではない)、重複排除されたコミットハッシュのsetが返されます。`verify_cleanup.py` は `from scan_repo import grep_all_commits` で同一実装を再利用しており、「スキャン」と「検証」の挙動に乖離が生じないよう担保しています。

プライベートルールを公開リポジトリに含めない設計:Layer 3はプライベートドメイン一覧をハードコードせず、実行時にユーザー独自のgitleaks TOMLから特定の2つのルールID(private-domain-context / private-ip-context)の正規表現のみを抽出し、さらに任意の行単位identitiesファイル(各行をre.escapeしてリテラルとして扱う)を読み込みます。

github-sensitive-data-cleanup/scripts/scan_repo.py
LAYER3_RULE_IDS = ["private-domain-context", "private-ip-context"]
動作の仕組み:「公開Skillに実際のプライベートドメインを含められない」という矛盾を解決します。ルールはユーザー側(`~/scripts/git-pii-guard/gitleaks.toml` または `.pii-patterns`)に保持し、Skill側は抽出機能のみを提供します。`DEFAULT_PATTERNS` にも意図的に汎用パターン(10./172.16-31./192.168. サブネットおよび電話番号)のみを配置し、コメントに `Do NOT hardcode real private domains here` と明記しています。TOMLの解析には標準ライブラリの `tomllib`(3.11以降)を優先し、古い環境では三重引用符および二重引用符の正規表現のみに対応する最小限のフォールバックパーサーを使用します。

履歴書き換え前の強制バックアップゲート:a) `git-filter-repo` がPATHに存在し実行可能であることの確認、b) ワーキングツリーがクリーンであることの確認(`git status --short` に出力があれば即座に中断)、c) `git bundle create --all` によるバックアップと直後の `git bundle verify` による検証を実施し、いずれかのステップが失敗した場合は書き換えを行わずに即時終了します。

github-sensitive-data-cleanup/scripts/rewrite_history.py
raise RuntimeError(f"Backup verification failed: {verify.stderr}")
メイン処理の順序:`is_dir(.git)` → replacementsファイルの存在確認 → message-replacementsファイルの存在確認 → `shutil.which(git-filter-repo)` → `--version` による実行可能性確認 → `check_clean_working_tree()` → 破壊的操作の警告バナー表示 → `--yes` の要求 → バックアップ → 書き換え。バックアップ失敗時は `CalledProcessError`/`RuntimeError` を捕捉して `exit(1)` で終了します。書き換えが途中で失敗した場合もバックアップの保存先を明示的に出力します。

履歴書き換えの本体は `git-filter-repo --force --replace-text <file>` であり、コミットメッセージを対象とする `--replace-message <file>` の追加指定も可能です。これにより、blobのみを変更してコミットメッセージ内に機密識別子が残ってしまう問題(v1.1.0で修正)を防止します。

github-sensitive-data-cleanup/scripts/rewrite_history.py
cmd += ["--replace-message", str(message_replacements_path)]
書き換え完了後、同一名称のJSONレポート(`backup_path.with_suffix(".json")`)を出力します。これには処理前後に `git show-ref --heads` で取得した `old_heads`/`new_heads` が記録され、次のステップとして `verify_cleanup.py`、続いて `safe_push.py` を実行するよう案内が出力されます。なお、`--force` は `git-filter-repo` に渡されるオプション(新規クローン保護を解除するため)であり、`git push` のforceオプションではありません。

検証フェーズも2系統のアプローチを採用し、「2つの検査手法が同一の死角を共有する」障害パターンを防ぎます。blobチャネルでは全コミットに対して `git grep` を実行し、メッセージチャネルでは `git log --all --format=%H%x1f%B%x1e` を用いて各コミットメッセージを抽出・マッチングします。不合格時には単なる件数ではなく該当するコミットハッシュ(上位10件)を出力します。

github-sensitive-data-cleanup/scripts/verify_cleanup.py
"--format=%H%x1f%B%x1e", "--no-color"],
検証対象のパターンは書き換え時に使用したreplacementsファイルから直接逆引き抽出されます(`extract_patterns_from_replacements` が `literal:`、`regex:`、プレーン文字列を解析)。そのため、書き換え後に `.pii-patterns` が変更されていても影響を受けません。いずれかのパターンがヒットするかエラーが発生した場合、`VERIFICATION FAILED` を出力して `exit(1)` で終了し、完全にクリーンな場合のみ `VERIFICATION PASSED` を出力します。リテラルパターンは `re.escape` 処理後にPCRE grepに渡されます。

プッシュ処理はフェイルクローズ(安全側に倒す)のゲートを設けています。まず `gh repo view --json visibility,isPrivate,stargazerCount,forkCount,owner,name` を実行し、作業ディレクトリからリポジトリを判定します(owner/repo文字列の推測は行いません)。ghコマンドの失敗やキーの欠落がある場合は推測を行わずに即時中断します。公開リポジトリかつ `forkCount > 0` の場合は警告を出力し、`--yes` の指定がなければ終了します。プッシュはまず `--force-with-lease` を試行し、標準エラー出力に stale info が確認された場合に限り1回のみ `--force` へのフォールバックを許可します。

github-sensitive-data-cleanup/scripts/safe_push.py
if "stale info" in result.stderr.lower():
動作の仕組み:「force pushの前に、第三者にフォークされた公開リポジトリではないことを確認する」という確認事項を、エージェントの裁量ではなく機械的に検証可能なステップへ変換しています。可視性判定の順序は、検証 → 確認(`--yes`) → プッシュの順です。キー欠落時のエラー文は `Aborting rather than using fallback values.` であり、推測による続行を排除しています。スクリプト全体を通して `--no-verify` を付加する処理は一切存在しません。

2コア機能

014層構造の機密データスキャン(gitleaks + カスタム正規表現 + プライベートコンテキスト抽出 + AIセマンティックレビュー判定フラグ)
02単なるHEADではなく、コミット全履歴(`--all`)を対象としたバッチ分割 `git grep --perl-regexp` による検索と該当コミットハッシュの特定
03プライベートルールの外部化:ユーザー独自のgitleaks設定から指定ルールIDの正規表現のみを抽出し、公開Skill内に実際の社内ドメインを保持しない設計
04強制バックアップおよび検証ゲートを伴う履歴書き換え(`git bundle create --all` + `git bundle verify`、失敗時は即時中断)
05コミットメッセージの書き換えと検証チャネル(`--replace-message` / `git log --all` の解析)によるblob単体処理の死角補正
06プッシュ実行前のリポジトリ公開設定およびフォーク数の自動照合(メタデータ欠落時のプッシュ拒否)
07段階的な強制プッシュ制御:`--force-with-lease` を最優先とし、stale info検出時のみ1回限り `--force` へフォールバック(`--no-verify` の使用は拒否)
08インシデント事例に基づくナレッジと手動エスカレーション条件の定義(50件以上のフォークが存在し有効なシークレットを含む場合などにおける人間への確認要請)

3外部依存関係

KindDependency / Endpoint
cligitleaks(Layer 1 密钥扫描)
cligitleaks detect(子进程实参:--source / --report-format json / --report-path / --verbose)
cligit-filter-repo(历史重写,须在 PATH 且 --version 可执行)
cligit(bundle create --all / bundle verify / status --short / show-ref --heads / rev-list --all / grep --perl-regexp / log --all / push --force-with-lease|--force)
cligh(GitHub CLI,用于仓库可见性与 fork 数核查)
apiGitHub REST API(由 gh repo view 隐式访问;源码内无字面 URL,端点归属 GitHub)
networkPyPI(文档命令 `uv run --with gitpython ...` 会要求 uv 从包索引获取 gitpython;四个脚本实际零 gitpython import,属文档声明依赖——[INFERENCE] 端点归属,源码内无 URL)
packagegitpython(SKILL.md 与四个脚本 docstring 的命令示例中声明;代码无 import,属未使用的声明依赖)
cliuv(文档规定的运行器:uv run --with gitpython / uv run scripts/...)
clidate(取 UTC 时间戳写入报告 scanned_at)
clibrew(仅安装说明:git-filter-repo / gitleaks / gh)
cliBFG Repo-Cleaner(参考文档里的备选工具,需 Java;未被脚本调用)
network用户侧的私有规则/身份清单文件(非网络端点,但属外部运行时输入):私有 gitleaks.toml、identities.txt、repo 根 .pii-patterns

4推奨統制措置と判定根拠

安全運用のための推奨統制措置
Agent 向け
段階的・都度認可、サンドボックス推奨
管理者向け
承認フロー、ロールバック可能、全履歴監査
判定根拠(ファイルパスと抜粋)
  • 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の一時レポートファイルを作成・削除します。
監査ノート: 以下の3点の実装要件によりリスク評価を引き上げています。①不可逆な破壊的処理の存在:`rewrite_history.py` は対象リポジトリに対して直接 `git filter-repo --force` を実行し、`safe_push.py` はGitHubリモートへの強制プッシュ(`--force-with-lease` 実行後、stale info検出時に1回限り `--force` へフォールバック)を行うため、実行後にフォーク先やキャッシュされた旧履歴を回収することは不可能です。②ユーザーの機密設定ファイルの読み込み:`--identities-file`、`--gitleaks-config`、`.pii-patterns`、replacementsファイルなどに実際の社内ドメイン、内部IP、識別名、マスキング前の平文が含まれます。③外部パッケージへの依存:ドキュメント内のコマンド例に `uv run --with gitpython` の指定があり、パッケージインデックスからの取得が発生します(スクリプト内での直接のimportはありません)。一方で、本Skillにはクリーンなワーキングツリーの検証、bundleバックアップと検証、明示的な `--yes` 要求、`gh` による公開範囲確認(メタデータ欠落時は中止)、lease優先プッシュ、`--no-verify` の徹底排除など堅牢な安全機能が組み込まれており、破壊的な操作はユーザーがSKILL.mdの手順に従って明示的にスクリプトを実行した場合にのみ発生します。スキャン用途(`scan_repo.py` / `verify_cleanup.py`:デフォルトで変更なし・外部通信なし)のみを実行する場合のリスクは低水準に留まりますが、履歴の書き換えやプッシュを伴う場合は高警戒レベルとして扱い、事前に `--repo`、`--branch`、`--backup` の対象パラメータを厳格に確認する必要があります。

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結論

  • 履歴の書き換え処理がエージェントの裁量任せではなく、機械的に検証可能なゲートに分解されています(クリーンなワーキングツリー → bundleバックアップ → bundle検証 → `--yes` 確認 → 書き換え実行。いずれかのステップが失敗した場合は即座に停止)。
  • プッシュ前の公開範囲確認がフェイルクローズ設計になっています(ghコマンドの利用不可やメタデータのキー不足時は即座にプッシュを拒否し、URLやディレクトリ名から公開状態を推測しません)。
  • blobとコミットメッセージの2系統による検証を採用しており、単一チェックによる死角を排除し、検証失敗時には該当するコミットハッシュを提示して原因箇所の特定を容易にします。
  • 公開リポジトリに社内情報を保持しません(実際のドメイン、IP、識別名はユーザー側の設定ファイルに留め、Skill側は抽出・照合ロジックのみを提供することで、クリーンアップツール自体が漏洩源になる事態を防ぎます)。
  • ツールの適用境界を明確化し過度な安全性を保証しません(認証情報のローテーション、GitHub側の内部キャッシュやフォークの削除、フックのバイパスは行わず、「漏洩した情報は第三者に閲覧されたものとして扱う」原則を徹底します)。
  • 最適な用途: シークレット、プライベートドメイン、社内IP、個人情報などを誤ってGitHubにプッシュしてしまい、「スキャン → バックアップ → コミットメッセージを含む全履歴の書き換え → 2系統での検証 → 公開範囲の確認後のプッシュ」という一連の是正フローを必要とする個人や開発チームに適しています。また、「force push前に公開範囲とバックアップを必ず検証する」運用手順を厳密に順守したいリポジトリ管理者にも適しています。運用上最も安全なアプローチは、まず `scan_repo.py` や `verify_cleanup.py`(読み取り専用・ネットワーク通信なし)を実行して検出内容を確認し、人間が replacements ファイルおよび `--repo`/`--remote`/`--branch`/`--backup` の各引数を精査した上で、書き換えとプッシュを実行することです。
    不向きな用途: 本ツールの実行のみをもって「漏洩が完全に無効化された」と見なす用途には適していません(GitHub側のキャッシュの削除、フォークされたリポジトリの回収、認証情報の無効化・再発行は行われず、Layer 4のセマンティックレビューも網羅性を完全に保証するものではありません)。複数リポジトリに対する完全自動・無人環境での一括書き換えや一括強制プッシュには適していません(リモートやブランチのホワイトリスト機能はなく、`--yes` が唯一の安全確認用ゲートです)。履歴を書き換えずに解決したい最小限の対応(新規コミットでのみ漏洩しており、認証情報のローテーションと通常のrevertおよび.gitignoreの追加で対応可能なケース)には適していません。また、Git管理外のリポジトリ、force push権限のない環境、既存のPull Requestブランチが無効化される影響を許容できない共同開発リポジトリにも適していません。
    Install Agent-Ready
    ① Verified Mirror 2026-09-15
    Option A · Direct DownloadDownload github-sensitive-data-cleanup.tar.gz
    sha256: aa1ae4b1f420e74a…
    Option B · Copy Guide for Agent
    install.json
    Agent はこの JSON ガイドから自動的にダウンロードして検証します。
    ② Upstream GitHub
    GitHub Repo ↗
    Pinned to commit d5c4678cb5.