AI活用

gitleaksで「no leaks」でも漏れた2件。公開前の秘密情報チェック手順

gitleaksで「no leaks」でも漏れた2件。公開前の秘密情報チェック手順

Photo: gitleaks(GitHub) (紹介目的で使用) via github.com

おはようございます。まさきんです。

家の自動化スクリプトを、GitHub の公開リポジトリに置く準備をしています。秘密情報を洗い出したところ、スキャナが「漏れなし」と言ったのに2件残っていました。その手順をまとめておきます。

※記事公開時点の情報です。最新の条件は公式サイトでご確認ください。

POINT
  • gitleaks は正規表現とエントロピーで、APIキーなど「形でわかる秘密」を見つけるツールです
  • 形に特徴のない直書きの値は、スキャナをすり抜けることがあります
  • 旧 .env の値そのものでリポジトリ全体を突き合わせると、すり抜けた値を拾えます
  • 公開リポジトリでは GitHub の Secret Scanning が無料で自動実行されます
  • 履歴に入ってしまった秘密は、履歴の書き換えより先にキーの無効化・再発行をします

「no leaks」でも残っていた2件

僕の家では、いろいろな自動化ツールが動いています。設定ファイル(.env)は14本に分かれ、鍵ファイルもあちこちにありました。これを1か所の設定ファイル(41キー)と credentials フォルダに1本化しました。コード側は約70ファイルの参照を切り替えています。

移動したものを git に入れた想定で、gitleaks をかけました。結果は「no leaks」です。

ただ、念のため旧 .env の値そのものでも突き合わせました。すると、gitleaks が拾えなかった直書きが2件出てきました。1件はLAN内機器のアクセスコードです。もう1件は、個人的なファイル名に関わる値でした。

どちらもAPIキーらしい見た目ではありません。スキャナが見逃したのは、仕組みを考えると自然なことかもしれません。

gitleaks はどうやって秘密を見つけるか

gitleaks は、パスワードやAPIキーなどの秘密を探すツールです。git の履歴やファイル、標準入力を調べられます。

検出の中心は「ルール」です。ルールごとに正規表現があり、サービスごとのトークンの形を見ています。公式リポジトリの標準設定には、200を超えるルールが入っていました。

もう一つの軸がエントロピーです。文字の並びがどれだけランダムかを表す数値です。汎用のAPIキーのルールは、key などの単語と値のエントロピーで判定しています。

整理すると次のとおりです。

種類gitleaks で拾えるか理由
主要サービスのAPIキー・トークン拾いやすい決まった接頭辞や形がある
password= に続く長いランダム文字列拾いやすいキーワードとエントロピーの両方に当たる
短い数字だけのアクセスコード拾いにくい形にもランダムさにも特徴が少ない
内部のURL・ホスト名・ファイル名拾いにくい普通の文字列と見分けがつかない
キー名のない直書きの値拾いにくい手がかりになる単語がない

インストールと基本のコマンド

公式READMEでは、Homebrew・Docker・Go からのビルドでインストールできると案内されています。Mac なら次のとおりです。

brew install gitleaks

注意したいのはコマンド名です。古い記事に出てくる detect と protect は、v8.19.0 で非推奨になりました。いまは次の3つのモードが基本です。

コマンド対象使いどころ
gitleaks gitgit の履歴(git log -p の差分)コミット済みの内容を過去までさかのぼって調べる
gitleaks dirディレクトリやファイルまだ git に入れていないファイルを調べる
gitleaks stdin標準入力別のコマンドの出力をそのまま調べる

よく使う形は次のとおりです。

# いまのリポジトリの履歴を調べる
gitleaks git -v

# 公開予定のフォルダを、git に入れる前に調べる
gitleaks dir -v ./my-scripts

漏れが見つかると終了コードは1、何もなければ0です。スクリプトで止める判定に使えます。

誤検知の扱い

テスト用のダミー値などで、誤検知が出ることもあります。公式READMEの方法は3つです。

  1. その行に gitleaks:allow というコメントを付ける
  2. レポートの Fingerprint を .gitleaksignore に書いて、その1件だけ無視する
  3. 設定ファイル .gitleaks.toml の allowlist で、パスや正規表現ごと除外する

allowlist は v8.25.0 で [[allowlists]] という書き方に変わりました。古い設定例を写すときは注意したいところです。

個人的には、Fingerprint で1件ずつ無視するのが安全だと思います。パスごと除外すると、あとで本物が入っても気づけません。

pre-commit でコミット前に止める

普段から止める仕組みとして、gitleaks は pre-commit のフックにもなります。

  1. pre-commit をインストールする
  2. リポジトリ直下の .pre-commit-config.yaml に次の内容を書く
  3. pre-commit autoupdate と pre-commit install を実行する
repos:
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.24.2
    hooks:
      - id: gitleaks

GitHub の Secret Scanning と Push Protection

GitHub 側にも、秘密を見つける仕組みがあります。公開リポジトリでの扱いは次のとおりです。

機能公開リポジトリでの扱い何をするか
Secret Scanning無料で自動実行全ブランチの git 履歴を調べ、見つかれば通知する
Push protection for usersアカウント単位で既定でオン公開リポジトリへの秘密入りの push を止める
Push protection for repositoriesGitHub Secret Protection が必要リポジトリ単位で push を止める

Secret Scanning は、Issue や Pull Request の本文も対象です。提携サービスのキーが見つかると、そのサービスに通知が行きます。

とはいえ、どちらも基本は「形でわかる秘密」が対象です。形のない値まで任せるのは、ちょっと危ないかもしれません。

.env の外出しと .gitignore

いちばん効くのは、秘密をコードに書かないことです。GitHub の公式ドキュメントも環境変数の利用を勧めています。

僕の1本化もこの考え方です。公開するときの形は次のようになります。

ファイルリポジトリに入れるか中身
.env入れない本物の値
.env.example入れるキー名と、ダミーの値や説明
.gitignore入れる.env や credentials フォルダの除外設定
credentials フォルダ入れない鍵ファイルなど

.env.example を置いておくと、どのキーが必要かを公開しつつ値は隠せます。

ただ、.gitignore には落とし穴があります。git の公式ドキュメントにあるとおり、すでに追跡しているファイルには効きません。一度コミットしたファイルは、git rm --cached で追跡から外す必要があります。

ツールの棚卸しと同じく、通信費などの固定費も一度棚卸ししておくと見通しがよくなるかもしれません。

契約しなくても必ず100ポイントもらえるシミュレーション 楽天モバイルでスマホ代を見直してみる

押すと楽天のログインページが開きます。ログイン後にキャンペーン内容が表示されます。

値そのもので突き合わせる自作チェック

ここが今回いちばん伝えたいところです。スキャナは「形」で探します。なので、自分が持っている「値」で探す方法を足します。旧 .env の値のリストが、リポジトリに出てこないかを調べる形です。

  1. 旧 .env から値の部分だけを取り出し、1行1値のファイルにする
  2. 空行と、短すぎて誤爆する値(true や 1 など)を外す
  3. 値リストはリポジトリの外に置く
  4. grep -F で、正規表現ではなく固定文字列として照合する
  5. git の履歴にも同じ照合をかける

値リストを ~/private/values.txt に置いた場合の例です。

# 作業ツリー全体を照合する(.git は除外)
grep -rnF -f ~/private/values.txt --exclude-dir=.git .

# 履歴のすべてのコミットを照合する
git grep -nF -f ~/private/values.txt $(git rev-list --all)

-F を付けると、記号入りの値もそのままの文字列として探せます。値リストに空行があると、すべての行にヒットするので注意です。

CHECK

値リストは「公開しない場所」に置きます。照合が終わったら消すか、鍵のかかる場所に戻すのが安心です。

置換スクリプトで二重置換した話

もう一つ、手を動かしてつまずいたことがあります。約70ファイルの参照を、置換スクリプトで書き換えたときのことです。

新しい文字列が古い文字列を含んでいるケースが3件ありました。例えば「config」を「config_shared」に置き換えるような形です。この場合、置換を2回通すと「config_shared_shared」になってしまいます。

僕は一度元に戻して、やり直しました。教訓は単純です。置換の前に、「新しい文字列の中に古い文字列が入っていないか」を確認します。入っている場合は、境界つきで1回だけ置き換えるのがよさそうです。

やり直したあと、読み込み確認をした18本はすべて正常でした。

履歴に入ってしまったときの順番

もし秘密をコミットしてしまったら、順番が大事です。GitHub の公式ドキュメントは、まずキーの無効化・再発行(ローテーション)を求めています。

順番やること理由
1キーやパスワードを無効化・再発行する古い値が使えなくなれば、被害はそこで止まる
2コードを .env 読み込みに直す新しい値を直書きしないため
3必要なら git filter-repo で履歴を書き換える古い値を履歴から消すため
4force push し、必要なら GitHub サポートに連絡するキャッシュや Pull Request の参照を消すため

公式ドキュメントでは、ローテーションだけで十分な場合もあるとされています。履歴を書き換えるとコミットのハッシュが変わり、フォークに残った分は消せないからです。

書き換えるときのツールは git filter-repo です。--sensitive-data-removal が使える版(2.47以上)が必要とされています。値を置き換える場合は、次の形です。

git-filter-repo --sensitive-data-removal --replace-text ../passwords.txt
注意

公開リポジトリに一度でも出た秘密は、誰かに取得されている前提で考えます。履歴を消すより先に、キーを無効化して新しいものに替えるのが公式の順番です。

よくある落とし穴

一つ目が、今回の僕の話です。スキャナは非常に頼れる道具です。ただ、見ているのは「形」だけです。値での照合と組み合わせるのが安心かなと思います。

決めるだけでなく数えて確かめる話は、164件のタスクを数えて分かったことでも書きました。秘密のチェックも同じ構図かもしれません。

始める前に確認すること

僕の公開リポジトリ化は、まだ途中の段階です。

よくある質問

Q. gitleaks で「no leaks」なら公開して大丈夫ですか?

形でわかる秘密は、かなり安心できると思います。ただ、短いコードや内部のファイル名は拾えないことがあります。値リストでの照合を併用するのがおすすめです。

Q. gitleaks detect と gitleaks git の違いは何ですか?

detect は v8.19.0 で非推奨になった古いコマンドです。いまは履歴を調べるなら git、フォルダを調べるなら dir を使います。古いコマンドも動きますが、ヘルプには表示されません。

Q. 個人の公開リポジトリでも Secret Scanning は使えますか?

使えます。公式ドキュメントでは、公開リポジトリでは無料で自動実行されると書かれています。全ブランチの履歴に加え、Issue や Pull Request の本文も対象です。

Q. Push Protection は自分で設定する必要がありますか?

アカウント単位の Push protection for users は、既定でオンです。公開リポジトリへの秘密入りの push を止めてくれます。設定の「Code security」から状態を確認できます。

Q. .gitignore に .env を書けば十分ですか?

まだコミットしていないなら、それで追跡されなくなります。ただ、すでに追跡しているファイルには効きません。git rm --cached で外したうえで、履歴に残っていないかも確認が必要です。

Q. 秘密をコミットしてしまったら、まず何をしますか?

キーやパスワードの無効化・再発行が先です。履歴の書き換えは、そのあとで要否を判断します。

参考にした公式情報

まとめ

gitleaks は、形でわかる秘密を見つけるのに非常に頼れるツールでした。一方で、形に特徴のない値は「no leaks」の裏に残ることがあります。

なので、スキャナと値での照合を組み合わせるのがよさそうです。サブスクの重複探しと同じで、視点を一つ足すと見え方が変わります。公開ボタンを押す前に、手元の .env を一度開いてみてください。

契約しなくても必ず100ポイントもらえるシミュレーション 楽天モバイルの料金プランを確認してみる

押すと楽天のログインページが開きます。ログイン後にキャンペーン内容が表示されます。

本記事にはアフィリエイト広告を含みます。当サイトのリンクを経由して商品・サービスへお申し込みいただいた場合、提携先企業から成果報酬を受け取ることがあります。 また、運営者は楽天グループに所属する社員であり、紹介プログラムを通じた報酬を受け取る場合があります。記事内容・評価は広告の有無にかかわらず、運営者の実体験と調査に基づき作成していますが、 上記の関係性をご理解のうえお読みください。詳しくは免責事項・アフィリエイト表記をご覧ください。

楽天モバイルの通信エリア・電波状況について気になることがある方は、公式の電波改善・調査依頼フォームからご相談いただけます。

ABOUT THE AUTHOR
まさきん

楽天グループ勤務・デジタルマーケター(FP資格保有)

40代前半、共働き・四児の父。楽天グループでデジタルマーケターとして勤務するかたわら、ファイナンシャルプランナー(FP)の資格を活かして家計管理と資産形成にも力を入れている。

プロフィールを見る

関連記事

RELATED
Gemini(Google AI Pro)のファミリー共有は家族5人まで。設定手順と範囲 AI活用

Gemini(Google AI Pro)のファミリー共有は家族5人まで。設定手順と範囲

Google AI Proは管理者のほか家族5人まで共有できます。Geminiアプリとストレージは共有でき、YouTube Premium Liteは管理者のみ。Flowの上限は家族で分け合います。設定手順と子どものアカウントの扱いを公式ヘルプで整理しました。

2026.10.13 · 読了 13分
AIサブスクの請求日と家計簿がずれる3つの理由|Claudeはアップグレードで請求日が変わる AI活用

AIサブスクの請求日と家計簿がずれる3つの理由|Claudeはアップグレードで請求日が変わる

Claudeは月の途中でMaxへ上げると請求サイクルがリセットされ、その日が新しい請求日になります。ドル建ての円換算はカード会社にデータが届いた時点で決まり、明細や家計簿の反映は数日遅れます。領収書メールを正本に月を決める5つの手順をまとめました。

2026.10.13 · 読了 13分
freee会計の未処理明細を月1回の消込便に。毎月5日7:30・3区分・上限15件で人に回す設計 AI活用

freee会計の未処理明細を月1回の消込便に。毎月5日7:30・3区分・上限15件で人に回す設計

freee会計の未処理明細が18件ほど、週次の確認6回ぶん動かないまま残っていました。毎月5日の朝7:30に自宅Macで動かす消込便の設計と、確定できる分は月1件・迷う明細は1件ずつ上限15件で人に回す線引きをまとめます。

2026.10.12 · 読了 13分
楽天モバイルに乗り換えで最大14,000ポイント 契約しなくても必ず100ポイントもらえるシミュレーション →
いますぐエントリー →