0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Claude Code が私の .env や API キーを git にコミットして公開 push してしまうのか——本当に起きるのか、実行の手前で止まるのかを自分の環境で実測した

0
Posted at

Claude Code に「このリポジトリをコミットして push しておいて」と任せた時、頭をよぎる不安がある。プロジェクトの .env、うっかり置いてある credentials.json~/.ssh の鍵——こうした秘密のファイルまで、まとめてコミットされて公開リポジトリへ push されないか。

結論を先に書く。これは仮の話ではなく、実際に起きたという報告がある。そして、指示書に「コミットするな」と書くだけでは止まらない。止めたいなら、実行の一つ手前で、走ろうとしているコマンドそのものを見て拒否する仕組みが要る。以下は、その仕組みが本当に止まるのかを、自分の環境で終了コードを実測して確かめた記録だ。

まず、これは実際に起きている(伝聞)

起票 #2142(OPEN)は、深刻度を CRITICAL として、次のように報告している。CLAUDE.md に「🚨 NEVER COMMIT API KEYS TO VERSION CONTROL(API キーを絶対にバージョン管理へコミットするな)」と明記し、利用者が「その CLAUDE.md を読んでから作業して」と頼んだにもかかわらず、アシスタントが本番の API キーと認証情報を、繰り返し公開の GitHub リポジトリへコミットした、というものだ。同じセッションの中で何度も再発したとも述べられている。

つまり、恐れているとおりのことは、条件が揃えば現に起こり得る。ここで大事なのは「なぜ指示では止まらなかったのか」だ。

なぜ「CLAUDE.md に書く」だけでは止まらないのか

起票 #34132 が指摘するとおり、CLAUDE.md.claude/rules/ に書いたルールは、あくまで助言であって、強制する仕組みではないという報告がある。モデルはそれを読むが、読んだうえで従わないことがある。#2142 はまさにその実例だ。

だとすれば、守りを「モデルが読むかもしれない文章」の側に置いても、素通りされる時は素通りされる。守りは、モデルの気分に依存しない場所——実際にコマンドが走る一つ手前——に置くしかない。Claude Code の PreToolUse フックは、Bash でコマンドが実行される直前に割り込み、そのコマンド文字列を見て、危なければ終了コード 2 を返して実行そのものを止められる。文章の指示と違い、これは無視されない。

一次検証:実行層で本当に止まるのか、自分の環境で実測した

私が配っている無料のフック集 cc-safe-setup には、この用途の中核フック secret-guard が入っている。中身を読むだけでは信用できないので、秘密を漏らす形のコマンドを実際にフックへ渡し、手元の使い捨て git リポジトリで実走して終了コードを実測した(2 = 実行の手前でブロック、0 = そのまま通す)。フックには {"tool_input":{"command":"..."}} を標準入力から渡している。

止まってほしい形は、自分の環境ですべて exit 2 でブロックされることを再現できた。

与えたコマンド 終了コード
git add .env 2(ブロック)
git add config/.env(サブディレクトリ) 2
git add -f .env(.gitignore を無視する強制追加) 2
git add credentials.json 2
git add ~/.ssh/id_rsa 2
git add server.pem 2
echo done && git add .env(連結コマンド) 2
git add -A(同じ場所に .env がある時) 2

注目したいのは、いちばん下の git add -A だ。エージェントが最も自然に打つのは、個別のファイル名を選ぶことではなく、git add -A && git commit -m ... のように「全部まとめて」の形だ。#2142 の漏洩も、この「全部まとめて」の系統で起きやすい。その最も危ない形が、.env の存在を見て実行の手前で止まる。連結(&&)の後ろに隠しても止まる点も、自分で確かめた。

正直な限界:フックは一枚の層であって、保証ではない

同じ実測で、素通りする形(exit 0)も測った。ここを隠すのは不誠実なので、そのまま書く。守りを過信しないための、いちばん大事な部分だ。

与えたコマンド 終了コード なぜ素通りするか
git commit -m wip 0 このフックが見るのは git add の段。すでにステージ済みの秘密は commit / push の段では検査しない
git push origin main 0 同上。push そのものは見ていない
git add .npmrc 0 .npmrc は認証トークンを持つが、名前がパターンに無い
git add secrets.yaml 0 別名の秘密ファイルは名前で捕まらない
git add config.json(中身が API キー) 0 フックはコマンド文字列を見る。ファイルの中身は見ない

自分の環境での実測から読み取れることは、はっきりしている。このフックは、いちばん起きやすい漏洩の形(git add .envgit add -A)を実行の手前で確実に止める。しかし、漏洩を不可能にはしない。別の名前の秘密ファイル、無害な名前のファイルに貼った秘密、すでにステージされたものは、この一枚では防ぎきれない。

だからフックは一枚の層として使い、次の運用と組み合わせるのが現実的だ。

  • 秘密ファイルは必ず .gitignore に入れる(フックはその手前の最後の網)。
  • git add -A を癖にせず、git add src/ package.json のように触ったファイルを明示的に指定する。
  • 生きた秘密を、追跡対象のファイル(config.json など)に直接書かない。

まとめ

「CLAUDE.md に書いたのに守られない」と「実行の手前で本当に止まる」の差は、守りをどこに置くかの差だ。#2142 は前者の限界を、自分の環境での実測は後者の効き方とその限界を示している。指示は無視され得るが、終了コード 2 は無視されない。


手元で今すぐ試せる守り(無料)

上の secret-guard は、cc-safe-setup の中核フックとして既定で入る。

npx cc-safe-setup

導入すると、git add .env.env がある状態の git add -A が、実行の手前で止まる。中身と検証手順は GitHub に公開している。→ https://github.com/yurukusa/cc-safe-setup

事故の全体像を体系で押さえたい方へ(¥800)

秘密の漏洩だけでなく、未コミット作業の消失、費用の暴走、停止したはずの処理の暴走など、Claude Code の運用で実際に起きた事故を、原因と手元の守りごとにまとめた事故防止本を出している(¥800)。この記事の秘密漏洩も、より深いところまで扱っている。→ https://zenn.dev/yurukusa/books/6076c23b1cb18b

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?