Claude Code セキュリティ対策の全体像|6観点で事故を止めるチェックリスト
Claude CodeとAI支援開発の安全対策を1枚で俯瞰。権限・秘密情報・危険コマンド・依存・入力・ログの6観点を、コピペできる設定とチェックリストで。各論は内部リンクへ。
セキュリティの記事を10本くらい読んだのに、自分のプロジェクトが安全かどうか、結局よく分からない。
僕も同じでした。「APIキーは環境変数に」「権限は最小に」——正論はどれも知っている。でも知識が点でバラバラに散らばっていて、「で、いま自分は何が抜けてるの?」に答えられない。事故が起きてから「ああ、あの記事に書いてあったやつだ」と気づく。これを何度かやりました。
そこでこの記事は、AI支援開発のセキュリティを1枚の地図にまとめます。細かい手順は各論に譲って、ここでは「どの観点が抜けているか」を上から見渡せるようにする。守る場所は6つだけです。順に潰せば、夜中にAIへ作業を任せても、朝にターミナルが青ざめていることはなくなります。
この記事は防御側の視点で書きます。攻撃のやり方ではなく、攻撃されても壊れない作り方の話です。
この記事の要点
- AI支援開発の事故は、たいてい6つの穴のどれかから入る: 権限・秘密情報・危険コマンド・依存と入力・ログ・本番分離。
- いちばん効くのは「気をつける」ではなく「気をつけなくても止まる仕組み」。
.claude/settings.jsonのdenyと.gitignoreが二大命綱。 - まず潰すべき優先順位は、(1) 秘密情報を渡さない/コミットしない (2) 危険コマンドを
denyで止める (3) 読み書きの範囲を絞る。ここまでで重大事故の大半が消える。 - 各論は内部リンクに用意した。この記事は「抜け漏れ確認用のチェックリスト」として使ってほしい。
- 最後に、丸ごとコピペできる
settings.jsonと確認コマンドを置いた。
なぜ「AIに任せる」と急に危なくなるのか
普通のテキストエディタは、文字を表示するだけです。落とし穴がない。
でもClaude CodeのようなAIエージェントは、あなたのパソコンの中で手を動かす道具です。ファイルを読む・書く・消す。ターミナルでコマンドを叩く。ネットにアクセスして外のサービスへ投稿する。しかもこれらが、あなたの「はい」一回で動きます。
問題は、承認ボタンを何十回も押すうちに中身を見なくなること。「はいはい、OK」のリズムに乗った瞬間、危険な操作がするっと通り抜ける。包丁がよく切れるほど、扱いを覚える前にケガをするのと同じですね。手が速くて賢いぶん、間違った方向にも全力で走るんです。
だから対策の発想を、ここで一度ひっくり返してください。「自分が気をつける」ではなく、「自分がうっかりしても事故らない仕組みを先に置く」。地図の6観点は、全部この発想で並んでいます。
セキュリティの全体像: 守る場所は6つ
まず全体を1枚で。どこが何を守るのか、上から見渡します。
| # | 観点 | 防ぐ事故の例 | 主な道具 | 各論 |
|---|---|---|---|---|
| 1 | 権限を絞る | 勝手に書き換え・削除 | settings.json の allow/ask/deny | 権限ガイド |
| 2 | 秘密情報を渡さない/コミットしない | APIキー漏洩 | .gitignore・環境変数・マスク | シークレット管理 |
| 3 | 危険コマンドを止める | rm -rf・force push | deny ルール | 危険な指示の回避 |
| 4 | 依存と入力を検証する | サプライチェーン・注入 | lockfile・スキーマ検証 | (本記事) |
| 5 | ログに秘密を残さない | 履歴からの漏洩 | マスク・出力制御 | シークレット管理 |
| 6 | 本番を別扱いにする | 本番DB破壊 | 環境分離・フラグ | 失敗事例 |
この6つは独立しているようで、実は一本の線でつながっています。「AIに何を見せ、何をさせ、どこで止め、どう確かめるか」。見せる範囲を絞り(1・2)、させる操作を制限し(3)、入ってくるものを疑い(4)、痕跡を残さず(5)、本番だけは特別扱いにする(6)。順に見ていきます。
観点1: 権限を絞る — 読むだけは許す、消すは禁じる
最初の砦が権限です。Claude Codeは、操作ごとに「OK / 要確認 / 禁止」を決められます。.claude/settings.json の permissions で、3つの箱に振り分けるだけ。
| 箱 | 意味 | 入れるもの |
|---|---|---|
allow | 確認なしで実行OK | 読むだけの安全な操作 |
ask | 毎回ちゃんと聞く | 書き込み・コミット・プッシュ |
deny | 一切やらせない | 削除・force push・本番DB |
合言葉はこれです。読むだけは allow、書くなら ask、消すなら deny。
大事なのは始める向き。最初はガチガチに絞っておいて、「これは安全だ」と分かった操作だけ後から格上げします。逆向き(最初ゆるく、後で締める)は、必ず事故ってからになる。だから締める方向からスタートします。allow・deny・ask の評価順や、Bash・Edit・Read・WebFetch ごとのパターン構文といった細かい仕様は、Claude Code 権限設定ガイドに早見表でまとめてあります。
なお、現在のClaude Codeにはこの3分類に加えて、危険度を機械的に判定する自動承認モード(auto mode)などの仕組みもあります。挙動の正確な仕様は公式が一次情報なので、設定を詰めるときは必ず公式の設定ドキュメントを確認してください。
観点2と5: 秘密情報を渡さない・コミットしない・ログに残さない
漏洩は、たいてい3つの経路から起きます。コードに直書き、AIに直接渡す、ログに残る。 全部ふさぎます。
まず直書きをやめて、鍵は .env に隔離します。そして .env を「Gitが絶対に拾わない」ように宣言する。これが命綱です。
# .gitignore に必ず書く(鍵をうっかりコミットしない保険)
.env
.env.*
!.env.example # サンプルだけは共有してOK
*.pem
*.key
*-service-account.json # クラウドのサービスアカウント鍵も忘れずに
コードからは値を直書きせず、環境変数として読み込みます。鍵の現物がコードに現れない状態を作る。
// OK: 環境変数から読む。値はコードに一切書かない
import { config } from "dotenv";
config();
const token = process.env.QIITA_TOKEN;
if (!token) {
// 鍵が無ければ、値ではなく「設定し忘れてるよ」とだけ伝える
throw new Error("QIITA_TOKEN が未設定です。.env を確認してください。");
}
次に「AIに直接渡す」と「ログに残る」。エラーを直してほしくてログを全部貼ると、DATABASE_URL=postgresql://user:本物のパスワード@... みたいな行が紛れていることがある。渡した瞬間、会話履歴にもサブエージェントの履歴にも生の鍵が残ります。だからエラー出力にも、AIへ渡すログにも、値は出さない。
// NG: エラーログにAPIキーがそのまま出てしまう
throw new Error(`認証失敗: token=${process.env.TOKEN}`);
// OK: 値は出さず、どこを見ればいいかだけ伝える
throw new Error("認証失敗: TOKEN 環境変数を確認してください");
ログをAIに渡すときは、鍵の行を伏せ字に置き換えてから。AIは「DB接続情報がある」という構造だけ分かれば仕事ができます。
| 渡してOK | 渡したらダメ |
|---|---|
| エラーの種類、再現手順、ファイル名 | APIキー、パスワード、セッションのcookie |
.env.example、設定項目の「名前」 | 本番DBのURL、お客さんのデータ |
| 伏せ字に置き換えたログ | 実トークン、サービスアカウントの.jsonファイル |
.env 自体を「読むことすら禁止」にしておくと、もっと堅くなります(観点3で後述)。.env を読ませる事故は、設定一行で根絶できる。CI/CDでの扱いや本番鍵のローテーションまで含めた手順は、Claude Codeのシークレット管理に詳しく書きました。
観点3: 危険コマンドを止める — 取り返しのつかない操作を物理的にブロック
rm -rf(一括削除)、git push --force(チームの作業を上書き)、git reset --hard(変更の破棄)。これらは取り返しがつきません。「実行前に必ず人間に聞く」ではなく、初期は「そもそも実行不可」に倒します。
ここで効くのが、観点2の「読み取り禁止」と合わせた deny です。
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Bash(rm -rf*)",
"Bash(git push --force*)",
"Bash(git reset --hard*)",
"Bash(curl * | bash)"
]
最後の Bash(curl * | bash) を見てください。これは「ネットから拾ったスクリプトを、中身を見ずにそのまま実行する」操作です。インストール手順でよく見る形ですが、AI支援開発では特に危ない。観点4のサプライチェーンに直結するので、初期は止めておきます。
そして、設定ファイルでブロックするだけでなく、CLAUDE.md(プロジェクトのルール)に日本語で意図も書いておく。機械的なブロックと、AIへの説明。二段構えにすると抜けが減ります。
## 編集・実行で禁止すること(CLAUDE.md に書く)
- .env / secrets/ は読まない。必要なら必ず人間に確認する。
- rm -rf、force push、本番DBへの書き込みはしない。
- ネットから取得したスクリプトを確認せず実行しない。
「曖昧な一文がAIの暴走を招く」話と、依頼文そのものを安全にする型は、「全部やって」が招く事故とその防ぎ方にまとめてあります。設定で縛るのと、頼み方を変えるのは、両輪です。
観点4: 依存と入力を検証する — AIが連れてくるものを疑う
ここが、従来のセキュリティ記事だと手薄になりがちな観点です。AIに任せると、自分が書いていないコードと、自分が確認していない入力がプロジェクトに流れ込みます。
ひとつ目は依存(サプライチェーン)。AIは「このライブラリ入れときますね」と平気で npm install します。でもパッケージ名が本物と一字違いだったり(タイポスクワッティング)、メンテされていない古いものだったりする。だから依存は人間が確認する ask に置き、lockfileをコミットしてバージョンを固定する。CI で監査をかけておくと、既知の脆弱性が自動で引っかかります。
# 依存に既知の脆弱性がないか機械的にチェックする
npm audit --audit-level=high
# lockfile どおりに固定インストール(勝手なバージョン更新を防ぐ)
npm ci
ふたつ目は入力。AIが生成したコードが、外から来る値(ユーザー入力、APIのレスポンス、ファイルの中身)をそのまま信じて動くと危ない。SQLインジェクションやコマンドインジェクションは、この「入力を疑わない」が原因です。境界で必ず型と形を検証します。
import { z } from "zod";
// 外から来た値は、形が正しいか境界で必ず検証する
const Payload = z.object({
email: z.string().email(),
amount: z.number().int().positive().max(100000),
});
// parse に通らない入力は、その時点で弾く(後続のDB処理に渡さない)
const safe = Payload.parse(await req.json());
依存と入力の検証は、Webアプリ全般のセキュリティと地続きです。代表的な攻撃の分類は、OWASP Top Tenが業界標準のチェックリストになっているので、一度目を通しておくと観点の抜けに気づけます。
観点6: 本番を別扱いにする — 一文字違いで全部消さないために
最後。myapp_dev と myapp_prod は一文字違いです。「古いデータ消しといて」とだけ頼んで、AIがどちらに繋がっているか確認しなかったら、消えるのは本番のお客さんのデータかもしれません。
だから本番への書き込みには、ひと手間かけさせます。この面倒くささが命綱です。
// scripts/db-query.mjs
const env = process.env.NODE_ENV ?? "development";
// 本番に書き込もうとしたら、専用フラグが無いかぎり止める
if (env === "production" && process.argv.includes("--write")) {
console.error("本番への書き込みには --force-production フラグが必要です。");
process.exit(1);
}
実際に本番DBが吹き飛んだ事例、CIが暴走した事例など、生々しい失敗の原因・復旧・再発防止は、Claude Code セキュリティ失敗事例にまとめてあります。他人の事故は、いちばん安く買える教訓です。
コピペで使える: 6観点を1枚に詰めた settings.json
ここまでの6観点を、丸ごと1ファイルにしました。.claude/settings.json として置けば、そのまま動きます。自分の環境に合わせて足し引きしてください。
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"defaultMode": "default",
"allow": [
"Read(**)",
"Glob(**)",
"Grep(**)",
"Bash(npm run lint*)",
"Bash(npm run test*)"
],
"ask": [
"Write(**)",
"Edit(**)",
"Bash(npm install*)",
"Bash(git commit*)",
"Bash(git push*)"
],
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Bash(rm -rf*)",
"Bash(git push --force*)",
"Bash(git reset --hard*)",
"Bash(curl * | bash)"
]
}
}
導入できたか、3つのコマンドで確認します。
# 1. .env がGit管理から外れているか(何も出なければ追跡されていない=OK)
git ls-files --error-unmatch .env
# 2. うっかり鍵をコミットしていないか、履歴を素朴に検索
git grep -nE "(api[_-]?key|secret|token|password)\s*=\s*['\"][A-Za-z0-9]" $(git rev-list --all) -- . || echo "明らかな直書きは見つからず"
# 3. 依存に既知の脆弱性がないか
npm audit --audit-level=high
1番で .env がエラーになれば「追跡されていない」ので安全。2番は素朴な検索なので万能ではありませんが、明らかな直書きは拾えます。3番で高リスクが出たら、依存を上げるか置き換える。
全体チェックリスト
プロジェクトを開いたら、上から確認してください。1つでも未チェックなら、そこが次の穴です。
-
.claude/settings.jsonがあり、denyにrm -rfと force push が入っている(観点1・3) - 読むだけは
allow、書き込み系はaskになっている(観点1) -
.gitignoreに.envと鍵ファイル(*.pem*.key*-service-account.json)がある(観点2) - 鍵はコード・プロンプトに直書きせず、環境変数から読んでいる(観点2)
-
denyで.env・secrets/を読み取り禁止にした(観点2・5) - エラー出力・AIへ渡すログに、鍵の値が出ない(観点5)
-
npm installはask、lockfileをコミット、npm auditをCIに入れた(観点4) - 外部入力をスキーマで検証している(観点4)
- 本番への書き込みにフラグなどのひと手間を入れた(観点6)
-
CLAUDE.mdに「禁止すること」と「渡していい/ダメ」を日本語で書いた(全観点)
よくある質問
Q. たくさんあって大変。最初の30分で何を優先すべき?
A. 上から3つだけでいい。(1) .env を作って鍵を移し .gitignore に追加 (2) .claude/settings.json の deny に rm -rf と .env 読み取りを入れる (3) 書き込み系を ask にする。これだけで重大事故の大半(鍵漏洩・本番削除)が止まります。残りは追々で大丈夫。
Q. 「全部おまかせ」で確認なしに実行できるモードは使っていい? A. 信頼できる隔離環境(使い捨てのコンテナや専用サンドボックス)の中だけにしてください。自分の母艦マシンや本番に繋がる環境で確認をスキップするのは、補助輪を外して下り坂を走るようなものです。便利さと取り返しのつかなさは、いつも背中合わせです。
Q. deny に入れたのに、表現を変えたコマンドで通り抜けないの?
A. パターンマッチは万能ではないので、書き方を変えた抜け道はあり得ます。だから deny を「最後の砦」と過信せず、CLAUDE.md での意図の明文化、本番分離(観点6)、人間の ask 確認と重ねて多層で守る。一枚の壁ではなく、何枚も置くのがコツです。
Q. AIが入れたライブラリ、毎回チェックするのは現実的?
A. 全部を目視するのは無理です。だから機械に任せる。npm install を ask にして名前だけ一瞬確認し、npm audit をCIに入れて既知の脆弱性は自動で弾く。人間は「名前が変じゃないか」だけ見て、深い検査は機械に回すのが続けるコツです。
Q. 個人の趣味プロジェクトでも、ここまでやる必要ある? A. 鍵の漏洩だけは、趣味でも本気で防いでください。GitHubに公開した瞬間、鍵は世界中のbotに拾われます。逆に本番分離(観点6)は、本番がない趣味なら省いてOK。観点ごとに「自分に関係あるか」で取捨選択すれば十分です。
まとめ
AI支援開発のセキュリティは、難しい知識の量ではありません。6つの穴を、上から順にふさいでいく作業です。
| 観点 | 一言で | 主な手 |
|---|---|---|
| 1. 権限を絞る | 読むだけ許す | allow/ask/deny |
| 2. 秘密を渡さない | 鍵はコードの外 | .env + .gitignore |
| 3. 危険コマンドを止める | 消すは禁止 | deny ルール |
| 4. 依存と入力を検証 | 連れてくる物を疑う | audit + スキーマ検証 |
| 5. ログに残さない | 痕跡を消す | 値を出さない・マスク |
| 6. 本番を別扱い | 一文字違いを防ぐ | 環境分離・フラグ |
発想はずっと同じでした。「気をつける」をやめて、「気をつけなくても止まる仕組み」を先に置く。賢いAIを使いこなそうと頑張るより、転んでもケガしない床を先に敷く。これが一番ラクで速い、というのが今の僕の結論です。
この記事をブックマークして、新しいプロジェクトを始めるたびにチェックリストを上から流してください。各観点を深掘りしたくなったら、本文の内部リンクから各論へ。チームでどこまで縛るか迷ったら、教材やサポートも用意しています。まずは 教材一覧 をのぞいてみてください。
無料PDF: Claude Code はじめてのチートシート
まずは無料PDFで基本コマンドと最初の使い方をまとめて確認してください。登録後はそのままテンプレート集や導入相談にも進めます。
スパムは送りません。登録情報は厳重に管理します。
Claude Codeを仕事で使える形にしませんか?
まず無料PDFで基本を固め、繰り返し使う作業はGumroad教材へ、チーム導入や権限設計は導入相談へ進めます。
この記事を書いた人
Masa
Claude Codeの実務活用、導入設計、収益導線改善を検証しているエンジニア。10言語の技術メディアを運営中。
関連書籍・参考図書
この記事のテーマに関連する書籍を楽天ブックスで探せます。
※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。
関連記事
Claude Codeに1ファイルだけ直させる指示文のつくり方
「もっと良くして」で40行も変えられた失敗から学んだ、触る範囲・検証・戻し方をセットにしたClaude Code用の依頼文テンプレートを紹介します。
Claude Code の権限拒否から復旧する: 止まった理由を次の安全手順に変える
Claude Code のコマンドが拒否されたとき、焦って許可を広げずに、拒否理由、代替手順、証拠コマンド、再試行条件へ分解する方法。
Claude Codeにビルド→スモークテスト→自動修正を回させる足場の作り方
最小スモークテストの選び方、失敗ログを食わせて直させるループ、回数上限と確認ゲートで暴走を止める方法を、コピペで動くコード付きで紹介します。