Claude Codeの情報漏洩対策|鍵はMacのキーチェーンへ

ノートパソコンの前で、小さな金庫に鍵を入れてほっとした顔の男性(色鉛筆調のイラスト)

この記事でわかること
・Claude Code(CLAUDE君)に、パスワードなどの秘密がまたo(`ω´ )o画面に出てしまった話と、その原因
・設定ファイル(mcp.json)にむき出しだった鍵を、Macのキーチェーン(金庫)に移した方法
・CLAUDE君が鍵の値を見なくても仕事ができる仕組みと、うっかりを止める「見張り」
・やってみて3回つまずいたところと、使っていない鍵の片付け方

スーツマンは毎日、CLAUDE君(Claude Code)に、WordPressへの下書き投稿や記事の修正、n8n(自動化ツール)の設定まで手伝ってもらっています。

そのために、WordPressにログインするための鍵(トークンやパスワード)を、CLAUDE君が使える場所に置いていたんですよね。

前回、その鍵のひとつ(JWTトークン)が、チャット画面に丸見えになっていた話を書きました。

MCPのJWTトークンがチャット画面に丸見えだった話

そのときの結論は「完璧な解決策はなかった」。そして「Macの認証情報の中に鍵を保存していくのがいちばんいいのかなぁ、まだまだ検討の余地がのこります」でした。

で、今回。

その「検討の余地」の続きをやっていたら……また、秘密が画面に出ました。(;´Д`A

この記事では、Claude Codeの情報漏洩対策として、鍵を全部Macのキーチェーンに移して、CLAUDE君が鍵の値を見なくても仕事ができる仕組みにした話を書きます。途中で3回つまずいたので、そこも正直に書いていきますね。

ノートパソコンの前で、小さな金庫に鍵を入れてほっとした顔の男性(色鉛筆調のイラスト)
スポンサーリンク

また秘密が画面に出た

きっかけはトークンの期限切れ

WordPressとCLAUDE君をつなぐ鍵(JWTトークン=WordPressに「この人はログインしていいよ」と証明する文字列)の期限が、10月29日に切れることになっていました。

作り直すついでに、やることリストにずっと残っていた「設定ファイルにむき出しで入っている鍵を、キーチェーンに移す」も片付けようと。

キーチェーンというのは、Macに最初から入っている金庫みたいなもので、パスワードなどを暗号化してしまっておける仕組みです。

あ、ちなみにn8nの鍵だけは、前にキーチェーンに移してありました。今回はそれと同じ形にそろえます。

「伏せたつもり」の表示から、2つ漏れた

まずCLAUDE君が、設定ファイル(mcp.json=CLAUDE君がほかのサービスとつながるための設定)にどんな項目があるかを確かめようとしました。

もちろん値は見せないように、CLAUDE君が自分で「伏せる」処理を書いて表示したんです。長い文字列や、tokenやsecretという言葉が入っているものは伏せる、という決め方で。

ところが・・・

伏せる決め方にあてはまらなかった短い秘密が2つ、そのまま画面に出ました。

GoogleのToDoリスト(Google Tasks)をつなぐための秘密と、WordPressのアプリケーションパスワード(外のツールからWordPressにログインするための専用パスワード)です。どちらも「長さ」で伏せるかを決めていたので、短かったせいですり抜けたみたいでした。

CLAUDE君はすぐに自分から「伏せる処理が漏れて、2つ出てしまいました。会話の記録に残ったので、出たものとして作り直すのがおすすめです」と報告してきました。

会話の記録がGitea(自分で立てているGitの置き場)に上がる設定になっていないかも、一緒に確かめました。上がらない設定にはなっていたんですが、会話自体はAIのサーバーに送られています。なので、作り直すことに。

このときの正直な気持ちは、これでした。

「やっぱり会話にでてしまいますね、クロードがKEYは読めない方針をやっぱりつらぬきましょう」

前回もそうでしたが、「CLAUDE君に気をつけてもらう」だけでは限界があるんですよね。

鍵はMacのキーチェーンへ:「読める」から「読まない仕組み」へ

前回の実験では、キーチェーンに入れても、CLAUDE君は鍵を読めてしまいました。CLAUDE君は自分(Macのユーザー)として動いているので、自分が開けられる金庫は、CLAUDE君も開けられるんですよね。

指紋認証つきにすれば読めなくなるけど、今度はCLAUDE君の自動投稿ができなくなる。それがジレンマでした。

今回CLAUDE君と話し合って出た答えは、

「読めるけど、読む場面そのものをなくす」

でした。

仕組みはこんな感じ

  • 鍵はMacのキーチェーンだけに置く(設定ファイルには書かない)
  • 鍵を入れるのはスーツマン本人。ターミナル(文字でMacを操作する画面)で専用の道具を動かして貼り付ける。入力は画面に出ないので、CLAUDE君は一度も値を見ない
  • CLAUDE君がWordPressにつなぐときは、「キーチェーンから取り出して、WordPressに送る」までを小さなスクリプト(自動で動く短いプログラム)が中でやる
  • CLAUDE君の手元には、「つないだ結果」だけが返ってくる

つまり、鍵を扱うのはスクリプトの中だけで、会話には一切出てこない、という形です。

ノートパソコンの前で、あごに手を当てて考える男性と、机の上の小さな金庫(色鉛筆調のイラスト)

「.claudeの中にあっていいの?」

道具(スクリプト)は、CLAUDE君の設定フォルダ(.claude)の中に作りました。で、スーツマンはここで引っかかったんです。

「ファイルが.claudeのなかになってますがいいんですか?」

答えは「大丈夫」でした。.claudeにあるのは鍵を入れるための道具だけで、鍵そのものはキーチェーンに入る。道具はGiteaにバックアップされますが、鍵は上がりません。ターミナルはどのフォルダで開いていても動きます。

道具の中身は、ほぼこれだけです。

# 画面に出さずに受け取って、キーチェーンにしまう
read -r -s NEW_VALUE
security add-generic-password -a "$USER" -s "項目名" -w "$NEW_VALUE" -U

-U は「同じ名前があれば上書き」という意味です。入れ直したいときも、同じコマンドでOK。

.envに鍵を書いている人へ

あ、ちなみに検索してみると、「Claude Codeに.envを読ませない」方法を探している人も多いみたいです。.env(アプリの鍵や設定を書いておくファイル)に鍵を書いているなら、Claude Codeの設定ファイル(settings.json)で、読むのを禁止できます。

"permissions": {
  "deny": ["Read(./.env)", "Read(./.env.*)"]
}

ただ、禁止しても、パソコンの中に鍵がむき出しで置いてあること自体は変わらないんですよね。なのでスーツマンは、そもそもパソコンの中に.envを作らない方針にしています。鍵は、使うサービスの設定画面(Vercelの環境変数など)か、今回のキーチェーンに入れる。これがいちばん安心な気がします。

やってみたら3回つまずいた

①「permission denied」で動かない

さっそくJWTを作り直して、ターミナルで道具を動かしたら・・・

ターミナルでpermission deniedと表示されている画面
「実行していいよ」の設定が外れていた

原因はCLAUDE君でした。道具を作ったあと、CLAUDE君がコメントを1行書き足したんですが、そのときに使った「安全に書き換える道具」が、ファイルの「実行していいよ」という設定を外してしまっていたんです。

道具のほうも直して、書き換えても元の設定を引き継ぐようにしてもらいました。

②「unbound variable」で止まる

もう一度動かしたら、今度は「SERVICE」: unbound variable」というエラー。「SERVICE」なんて名前の入れ物は知らないよ、という意味です。

Macに最初から入っている古いbash(コマンドを読んで動かす係)は、変数のすぐ後ろに日本語の「」」が続くと、それも名前の一部だと読んでしまうそうです。そんなことある?( ̄∇ ̄)

${SERVICE} のように括弧でくくったら直りました。今度はCLAUDE君が、ダミーの値を入れて・消して、ちゃんと動くのを確かめてから渡してくれました。

③パスワードを2回貼ってしまった

JWTのあとは、アプリケーションパスワードの作り直しです。ここでスーツマンがやらかしました。

「パスワードを2回 コマンド+Vでいれてしまって、みえなかったのでバックスペース長押しして、もう一回だけコマンドとVおしてエンター押しました はいってるといいのですが」

入力が画面に出ないので、どこまで消えたのか見えないんですよね。結果、ログインできず。

ここでCLAUDE君は、値は見ずに「形」だけを確かめてくれました。WordPressのアプリケーションパスワードは「4文字×6つ」(空白込みで29文字)の形なんですが、入っていたのは50文字。1回目の消し残りと2回目が混ざっていたんです。

見えない入力で間違えたら、消そうとせずにCtrl+C(今の操作を止めるキー)で止めて、最初からやり直す。これが正解でした。入れ直したら、ちゃんとログインできました。

WordPressのアプリケーションパスワードの一覧。今回作ったもの・古いもの・n8n用の3つが並んでいる
上が今回作ったもの。真ん中の古いものは取り消し、下のn8n用は残す

あ、もうひとつ。JWTを作ったあと、

「もしかしたら1時間でつくっちゃったかもです」

と心配になって画面を見たら、1時間のものは取り消してあって、有効なのは30日のものでした。

WordPress MCPのトークンの一覧。1時間のものと古いものは取り消し済みで、30日のものが有効になっている
1時間のものは取り消し済み。有効なのは30日のもの

30日がいちばん長いみたいなので、これからは毎月作り直しになりそうです。

使っていない鍵とつなぎ先も片付けた

本当に使っていないかは、記録で確かめる

「MCPサーバーはつかってるかつかってないかわかりませんがみてください」

MCPサーバーというのは、CLAUDE君がWordPressやGoogleなどのサービスとつながるための「つなぎ口」です。

CLAUDE君が会話の記録を調べて、実際に使った回数を数えました。最初は「10月に116回」と出てきて、え、そんなに?と思ったら、ツールの一覧に名前が載っていた分まで数えていたそうで(笑)。数え直したら、

  • WordPressのつなぎ口:最後に使ったのは10月4日。しかも、もうつながらない状態だった
  • Google Tasksのつなぎ口:使ったのは8月29日の1回だけ

どちらも外しました。外してしまえば、そもそも鍵がいらなくなるんですよね。

手順書の古いやり方も、新しい道具に置き換えてもらいました。散策記事で写真をWordPressに上げる流れもよく使うので、テスト用の画像を上げて・消して、ちゃんと動くのを確かめています。

消す前に「ほかと共用していないか」を確かめる

Google側に残っている秘密も消します。ここで気をつけたのが、n8nが使っているGoogleの設定と一緒になっていないか、です。間違えて消すと、n8nの通知などが止まってしまうので。

Google Cloudの認証情報の画面。n8n用のクライアントが3つ並んでいる
n8n用のクライアントは、別のプロジェクトに3つ。ここは消さない

プロジェクトの一覧を見たら、もう1つ「My Project 2872」という名前のないプロジェクトがあって、その中にGoogle Tasks用のものが1つだけ入っていました。

Google Cloudの別のプロジェクトに、Google Tasks MCP用のクライアントが1つだけある画面
Google Tasks用はこれ1つだけ

これだけを消して、プロジェクトもシャットダウンしました(30日間は元に戻せます)。

Google Cloudの削除保留中のリソースに、シャットダウンしたプロジェクトが入っている画面
削除保留中。30日たつと完全に消える

思わぬところにも鍵が残っていた

もうひとつ見つかったのが、~/.zprofile(ターミナルを開くたびに読まれる設定ファイル)に残っていた古い鍵です。

ここに書いてあると、ターミナルから動かしたプログラムなら何でも読めてしまう状態だったので、使っていないのを確かめてから消しました。

これで、設定ファイルに入っている鍵は0個になりました ♪( ´▽`)

「キーチェーンなら、もう読めない?」→見張りを付けた

最後に、ずっと気になっていたことを聞いてみました。

「キーチェーンにいれたら、クロードはもうよめないんですよね?」

CLAUDE君の答えは、正直でした。

「読めない」ではなく、「読まない」と「読まなくても使える」仕組み。キーチェーンは自分の権限なら取り出せるので、CLAUDE君も技術的には取り出せる。実際、スクリプトの中では取り出して使っている、と。

・・・やっぱりそうなんですね(;´Д`A

そのうえで、もっと固くする案を2つ出してくれました。

  • A:見張りを付ける。CLAUDE君が「鍵の値を取り出すコマンド」を打とうとしたら、Claude Codeの設定で自動的に止める
  • B:取り出すたびに、Macの「許可しますか?」を出す。確実だけど、記事の作業のたびに何十回もクリックすることになる

Aにすると毎回自分の確認がいるのかな?と思って聞いたら、いらないそうです。止めるのは「値を取り出すコマンドを直接打ったとき」だけで、ふだんの作業はそのまま。自分のターミナルにも影響なし。

「ではOK、そうしてください 安全になるのであれば。」

設定はこんな感じです(Claude Codeの設定ファイル settings.json に、コマンドを動かす前のチェックを足す)。

"hooks": {
  "PreToolUse": [
    {
      "matcher": "Bash",
      "hooks": [
        { "type": "command", "command": "python3 \"$HOME/.claude/scripts/keychain_guard.py\"" }
      ]
    }
  ]
}

入れたあと、止めるべきコマンド5通りは止まって、ふだんの作業5通りは通るのを確かめました。

ただ、これも完全な壁ではないそうです。CLAUDE君が新しくプログラムを書いて、その中から取り出すような回り道までは止められない。あくまで「うっかり」を機械的に防ぐもの、です。

前回の「AIに任せる=ある程度は信頼する」という結論は、今回も変わらないんですよね。でも、うっかりが起きにくい形には、だいぶ近づいた気がします。

机の上の小さな金庫と、その上で見張るように置かれた小さなベル(色鉛筆調のイラスト)

前と今をくらべると

鍵・設定前今
WordPressのJWT設定ファイルにむき出し(古いものはターミナルの設定にも)キーチェーンだけ(30日ごとに作り直し)
WordPressのアプリケーションパスワード設定ファイルにむき出しキーチェーンだけ・古いものは取り消し
Google Tasksの秘密設定ファイル+ターミナルの設定にむき出しクライアントごと削除・プロジェクトもシャットダウン
つなぎ口(MCPサーバー)WordPress・Google Tasksを含む5つ使っている3つだけ
設定ファイルに入っている鍵3つ0
見張りなし鍵を取り出すコマンドを自動で止める

まとめ:Claude Codeの情報漏洩対策は、鍵をAIに見せないこと

  • 「AIが伏せたつもり」の表示は信用しない。設定ファイルは中身を出さず、項目名だけを見る
  • いちばん確実なのは、AIが鍵を扱う場面そのものをなくすこと。それでも技術的には読めるので、見張りで二重にする
  • 出てしまったら、すぐ作り直す。消す前に、ほかの仕組みと共用していないかを確かめる
  • 使っていないつなぎ口や鍵は、記録で確かめてから片付ける
  • 見えない入力で間違えたら、消さずにCtrl+Cでやり直す

前回は「完璧な解決策はなかった」で終わりました。今回も完璧ではないけど、前回より一段、守りが上がった気がします。

鍵はAIに見せない。見せる場面も作らない。これが、今のスーツマンの答えです。

CLAUDE君やMCPを使っている同士の皆さん、一度、自分の設定ファイルに鍵がむき出しで入っていないか、項目名だけでも見てみてください。

あ、ちなみにPCを替えたら、キーチェーンの中身は引き継がれないので入れ直しが必要です。そのときはCLAUDE君に案内してもらう予定です。

Claudeのトークンが盗まれる事件を見て、自分のVSCode認証トークンを確認したら27件も溜まっていた話
SynologyにGiteaを入れたらAPIキーごとpushしてた話

☕ この記事、お役に立てましたか?

35歳から8年間、英語学習を続けてきた記録をこのブログに書いています。
よかったら応援していただけると、次の記事を書く励みになります!

コメントを残す

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です