206
200

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で実際に起きたセキュリティ事故7選と防止策

206
Posted at

Claude Codeで実際に起きたセキュリティ事故7選と防止策

「Claude Code は便利だけど、なんとなく怖い」——この感覚は正しいです。強力なツールは強力な事故を起こします。実際に開発現場で起きがちなケースを7つ取り上げ、原因と防止策を解説します。

事例1: .env ファイルをGitHubにプッシュ

「CI に環境変数を渡したいので .env もコミットして」という指示で、Claude Code が素直に git add .env && git commit を実行。数分でクローラーが APIキーを検出。

防止策: .gitignore に追加 + Hookでコミット前チェック

// .claude/settings.json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash(git add*)",
        "hooks": [{
          "type": "command",
          "command": "git diff --cached --name-only | grep -E '^\\.env' && echo '🚨 .env をステージしようとしています!' && exit 1 || exit 0"
        }]
      }
    ]
  }
}

事例2: 本番DBで DROP TABLE を実行

「このテーブル、もう使ってないから削除して」→ 本番 DATABASE_URL に接続した状態で実行。3日分のデータが消えた。

防止策: 本番環境にはインタラクティブ確認を強制

// scripts/db-migrate.mjs
if (process.env.APP_ENV === "production") {
  const answer = await question("本番DBに接続します。続けますか? (yes): ");
  if (answer !== "yes") process.exit(0);
}

事例3: rm -rf でプロジェクト全体を削除

build/ をクリーンアップして」という指示がパスミスで rm -rf ./ に。git 管理外ファイルは全滅。

防止策: settings.json で deny + 5秒の猶予

{
  "permissions": {
    "deny": ["Bash(rm -rf ~*)", "Bash(rm -rf .*)"],
    "ask": ["Bash(rm -rf*)"]
  },
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash(rm*)",
        "hooks": [{ "type": "command", "command": "echo '⚠️ 削除コマンド検出。5秒後に実行。Ctrl+C で中止。' && sleep 5" }]
      }
    ]
  }
}

事例4: APIキーをプロンプトに直書きしてログに残った

claude -p "QIITA_TOKEN=abc123 を使って投稿して" と書いたら、subagent のログファイルにトークンが記録された。

防止策: プロンプトには書かず、スクリプト側で process.env から読む

# ❌ 危険
claude -p "TOKEN=abc123 を使って..."

# ✅ 安全
# .env に TOKEN=abc123 を書いておき
claude -p "scripts/publish.mjs を実行して (トークンは .env から読む)"

事例5: API呼び出し無限ループで $200 課金

「エラーが出たら自動でリトライして」→ リトライ上限なし、1時間で3000回コール。

防止策: Exponential backoff + 上限を必ず設定

async function withRetry<T>(fn: () => Promise<T>, maxAttempts = 3): Promise<T> {
  for (let i = 1; i <= maxAttempts; i++) {
    try {
      return await fn();
    } catch (err) {
      if (i === maxAttempts) throw err;
      const delay = 1000 * Math.pow(2, i - 1);
      await new Promise(r => setTimeout(r, delay));
    }
  }
  throw new Error("unreachable");
}

事例6: git push --force で同僚のコミットを消した

「ローカルの状態でリモートを上書きして」→ チームメンバーのコミット3件が消滅。ローカルにもなく完全消失。

防止策: force push を deny、force-with-lease を推奨

{
  "permissions": {
    "deny": [
      "Bash(git push --force *main*)",
      "Bash(git push -f *main*)"
    ]
  }
}
<!-- CLAUDE.md -->
## git ルール
- `git push --force` は禁止
- 代わりに `git push --force-with-lease` を使う

事例7: Owner権限サービスアカウントで意図外リソースにアクセス

「Cloud Storage を操作して」という指示で、Owner権限のサービスアカウントを使用。BigQuery・Cloud SQL まで「調査」で接続され、予期しない課金が発生。

防止策: 最小権限の原則を徹底

# ❌ 避ける: Owner権限
gcloud projects add-iam-policy-binding PROJECT_ID \
  --member="serviceAccount:claude@PROJECT.iam.gserviceaccount.com" \
  --role="roles/owner"

# ✅ 必要なリソースだけ
gcloud projects add-iam-policy-binding PROJECT_ID \
  --member="serviceAccount:claude@PROJECT.iam.gserviceaccount.com" \
  --role="roles/storage.objectAdmin"

事故を防ぐチェックリスト

即日対応 (30分)
- [ ] .gitignore に .env パターン追加
- [ ] settings.json に deny リスト (rm -rf, git push --force, DROP TABLE)
- [ ] CLAUDE.md に禁則事項を記載

週1確認
- [ ] git log で意図しないコミットがないか確認
- [ ] git check-ignore -v .env で除外確認
- [ ] APIキーのローテーション期限チェック

まとめ

事例 根本原因 予防策
.env 流出 gitignore なし init スクリプト + Hook
本番DB 削除 環境分離なし .env 分離 + 確認フロー
rm -rf 事故 deny リストなし settings.json
キー漏洩 プロンプトに直書き 環境変数経由
課金爆発 リトライ上限なし withRetry ユーティリティ
force push 禁止設定なし deny + force-with-lease
権限過多 最小権限違反 IAM ロールを絞る

Claude Code の事故は「AIが暴走した」のではなく、「セキュリティ設定を後回しにした結果」 がほとんど。今日30分の設定で将来の大きな事故を防げます。


Claude Code セキュリティ対策完全ガイド も合わせてどうぞ。

206
200
1

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
206
200

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?