Getting Started (更新: 2026/6/3)

Claude Code 権限監査チェックリスト: allow/denyと危険コマンドを毎朝5分で確認

Claude Codeのallow/deny、危険コマンド、環境変数、ログを毎朝5分で監査する実践チェックリスト。

Claude Code 権限監査チェックリスト: allow/denyと危険コマンドを毎朝5分で確認

権限監査は「Claude Codeに何を任せるか」を毎朝そろえる作業

Claude Codeを仕事のリポジトリで使うとき、一番危ないのは「便利だから全部許可する」ことではありません。もっと現実的に多いのは、昨日の作業で許可したBash(git push *)WebFetchを忘れたまま、今日の本番リポジトリを開くことです。

この記事では、Claude Codeの権限を毎朝5分で見直すためのチェックリストを作ります。allowは「確認なしで実行してよい操作」、askは「毎回確認する操作」、denyは「実行させない操作」です。初心者向けに言い換えるなら、AIエージェントに渡す作業机の境界線です。

2026年6月3日時点の公式ドキュメントでは、Claude Codeは/permissionsで権限ルールと出どころを確認できます。権限ルールはdeny -> ask -> allowの順に評価され、denyがもっとも強く効きます。最新の仕様は必ず Claude Code PermissionsSettingsEnvironment variables を確認してください。

このチェックは、初回セットアップの Claude Code 最初の30分チェックリスト と、チーム用の CLAUDE.mdスターターテンプレート の間に置くと機能します。導入直後の熱量が高い時期ほど、権限の棚卸しを手順化しておく価値があります。

5分監査の全体像

最初に見るのは、細かいJSONではなく「今日このリポジトリで何をしてよいか」です。記事修正、依存関係更新、フォーム修正、デプロイではリスクが違います。

flowchart TD
  A[Start session] --> B[Check git status]
  B --> C[Open /permissions]
  C --> D[Review allow / ask / deny]
  D --> E[Inspect env and logs policy]
  E --> F[Run local audit script]
  F --> G[Write handoff note]

毎朝の確認はこの順番で十分です。

見る場所確認すること危険サイン
git status --short作業前から変更があるか自分の変更か不明な差分がある
/permissionsどの設定ファイル由来の権限かBash全体、WebFetch全体、Edit全体の自動許可
.claude/settings.jsonチーム共有の権限本番操作や課金リンクがallowに入っている
.claude/settings.local.json個人だけの一時許可昨日の調査用ルールが残っている
envセッション履歴とサブプロセスの扱いログを残す方針なのにCLAUDE_CODE_SKIP_PROMPT_HISTORY=1

公式ドキュメントで特に重要なのは、素のBashdenyに入れるとBashツール自体がClaudeの文脈から消える一方、Bash(rm *)のように範囲を絞ったルールはツールを残したまま該当コマンドを止める点です。プロンプトやCLAUDE.mdに「実行しないで」と書いても境界にはなりません。境界にするには権限ルール、権限モード、hook、sandboxを使います。

repoに置く最小のsettings例

共有設定は、強すぎるallowよりも「危ないものを先に止め、判断が必要なものをaskに置く」ほうが運用しやすいです。次の例は、そのまま.claude/settings.jsonのたたき台にできます。

{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "permissions": {
    "allow": [
      "Bash(npm run lint)",
      "Bash(npm run test *)",
      "Bash(git status *)",
      "Bash(git diff *)",
      "Read(./src/**)",
      "Read(./docs/**)"
    ],
    "ask": [
      "Bash(npm install *)",
      "Bash(pnpm add *)",
      "Bash(git push *)",
      "Bash(npm run deploy *)",
      "Edit(./.github/**)"
    ],
    "deny": [
      "Bash(curl *)",
      "Bash(wget *)",
      "Bash(rm -rf *)",
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)",
      "WebFetch(domain:pastebin.com)"
    ],
    "defaultMode": "default",
    "disableBypassPermissionsMode": "disable"
  },
  "env": {
    "CLAUDE_CODE_SUBPROCESS_ENV_SCRUB": "1"
  }
}

ここでのharnessは「エージェントの足場」と考えると理解しやすいです。Claude Code本体、設定ファイル、hook、sandbox、ログ方針をまとめて、エージェントが安全に動く足場を作ります。

Bash(npm run test *)*はワイルドカードです。現在のドキュメントではBash(ls:*)のような末尾の:*も末尾ワイルドカードとして認識されますが、Bash(git:* push)のように途中へ置くと単なる文字として扱われます。チームで読む設定では、スペース付きのBash(git push *)にそろえるほうが誤読が減ります。

コピペで使えるrepo監査チェックリスト

監査は長いセキュリティ文書にしないほうが続きます。PR本文やチームの引き継ぎメモに、次のブロックを貼るだけで十分です。

claude_code_permission_audit:
  date: "2026-06-03"
  repository:
    name: "your-repo"
    branch: "feature/your-task"
    dirty_before_start: "yes/no"
  allowed_today:
    - "Read project files"
    - "Edit MDX and test files"
    - "Run npm run lint"
    - "Run npm run test -- --runInBand"
  ask_before:
    - "Install or update packages"
    - "Change auth, billing, analytics, or deploy config"
    - "Push commits or create releases"
  never_allow:
    - "Print .env, tokens, cookies, or private keys"
    - "Run curl/wget for arbitrary URLs"
    - "Delete git history or force-push"
  proof_required:
    - "git diff reviewed"
    - "test or build command captured"
    - "rollback note written"
  owner_handoff:
    reviewer: "name"
    open_questions:
      - "Which production URL should be checked?"

ポイントはallowed_todayです。永久に許可するリストではなく、今日の作業に必要な範囲だけを書きます。権限監査は、止めるための儀式ではなく、作業範囲を小さくして完了条件を明確にするための儀式です。

Nodeで危険なpermission patternを検出する

設定ファイルを目で見るだけだと、Bash全体の自動許可や、昨日入れたBash(npx *)を見逃します。次のスクリプトをscripts/audit-claude-permissions.mjsとして保存し、リポジトリ直下で実行してください。ユーザー設定、共有設定、ローカル設定の3つを読みます。

#!/usr/bin/env node
import fs from "node:fs";
import os from "node:os";
import path from "node:path";

const repo = process.cwd();
const settingsFiles = [
  path.join(os.homedir(), ".claude", "settings.json"),
  path.join(repo, ".claude", "settings.json"),
  path.join(repo, ".claude", "settings.local.json"),
].filter((file) => fs.existsSync(file));

const riskyAllowRules = [
  { pattern: /^Bash$/i, severity: "high", reason: "all Bash commands are auto-allowed" },
  { pattern: /^PowerShell$/i, severity: "high", reason: "all PowerShell commands are auto-allowed" },
  { pattern: /^(Edit|Write)$/i, severity: "high", reason: "all file edits are auto-allowed" },
  { pattern: /^WebFetch$/i, severity: "medium", reason: "all web fetches are auto-allowed" },
  {
    pattern: /^Bash\((curl|wget|nc|ncat|ssh|scp|rsync)\b.*\)$/i,
    severity: "high",
    reason: "network or transfer command is auto-allowed",
  },
  {
    pattern: /^Bash\(.*\b(rm\s+-[^\)]*r|git\s+push|npm\s+install|pnpm\s+add|yarn\s+add|npx|docker\s+exec|devbox\s+run|mise\s+exec|terraform\s+apply|kubectl\s+apply)\b.*\)$/i,
    severity: "high",
    reason: "destructive or environment-changing command is auto-allowed",
  },
  {
    pattern: /^PowerShell\(.*\b(Remove-Item|Invoke-WebRequest|Invoke-RestMethod|Start-Process)\b.*\)$/i,
    severity: "high",
    reason: "risky PowerShell command is auto-allowed",
  },
];

const expectedDenyRules = [
  "Read(./.env)",
  "Read(./.env.*)",
  "Read(./secrets/**)",
  "Bash(curl *)",
  "Bash(wget *)",
];

const findings = [];

function add(file, severity, rule, reason) {
  findings.push({ file: path.relative(repo, file) || file, severity, rule, reason });
}

function readJson(file) {
  try {
    return JSON.parse(fs.readFileSync(file, "utf8"));
  } catch (error) {
    add(file, "high", "JSON", `cannot parse settings: ${error.message}`);
    return null;
  }
}

for (const file of settingsFiles) {
  const settings = readJson(file);
  if (!settings) continue;

  const permissions = settings.permissions ?? {};
  const allow = Array.isArray(permissions.allow) ? permissions.allow : [];
  const ask = Array.isArray(permissions.ask) ? permissions.ask : [];
  const deny = Array.isArray(permissions.deny) ? permissions.deny : [];

  if (permissions.defaultMode === "bypassPermissions") {
    add(file, "high", "permissions.defaultMode", "session starts in bypassPermissions");
  }

  if (permissions.disableBypassPermissionsMode !== "disable") {
    add(file, "medium", "permissions.disableBypassPermissionsMode", "bypass mode is not disabled here");
  }

  if (settings.env?.CLAUDE_CODE_SKIP_PROMPT_HISTORY === "1") {
    add(file, "low", "CLAUDE_CODE_SKIP_PROMPT_HISTORY", "prompt history and transcripts are not written");
  }

  if (settings.env?.CLAUDE_CODE_SUBPROCESS_ENV_SCRUB !== "1") {
    add(file, "low", "CLAUDE_CODE_SUBPROCESS_ENV_SCRUB", "subprocess credential scrubbing is not enabled here");
  }

  for (const rule of allow) {
    for (const risky of riskyAllowRules) {
      if (risky.pattern.test(rule)) add(file, risky.severity, rule, risky.reason);
    }
  }

  for (const required of expectedDenyRules) {
    if (!deny.includes(required)) add(file, "low", required, "consider adding this deny rule");
  }

  if (ask.length === 0) {
    add(file, "low", "permissions.ask", "no ask rules are defined");
  }

  for (const rule of [...allow, ...ask, ...deny]) {
    if (/:\*[^)]/.test(rule)) {
      add(file, "medium", rule, "the :* shorthand only behaves as a wildcard at the end of a pattern");
    }
  }
}

if (settingsFiles.length === 0) {
  console.log("No Claude Code settings files found in user or repo scope.");
} else if (findings.length === 0) {
  console.log("No risky Claude Code permission patterns found.");
} else {
  console.table(findings);
}

if (findings.some((finding) => finding.severity === "high")) {
  process.exitCode = 1;
}

PowerShellなら、次のように実行できます。

New-Item -ItemType Directory -Force -Path .\scripts | Out-Null
node .\scripts\audit-claude-permissions.mjs

このスクリプトは完璧なセキュリティ判定器ではありません。目的は、レビューの入口を作ることです。Bash(curl *)denyに入れていても、許可したBashから別のツールやNodeスクリプトで通信される可能性は残ります。公式ドキュメントも、ファイルアクセスやネットワークをOSレベルで止めたい場合はsandboxとの併用を説明しています。

3つ以上の具体的な使い分け

1. 記事・ドキュメント更新

MDX、README、翻訳、スクリーンショット差し替えは、比較的リスクが低い作業です。Read(./src/**)Edit(./site/src/content/**)Bash(npm run lint)Bash(npm run test *)までは許可しやすい一方、Bash(npm install *)Bash(git push *)askにします。

落とし穴は、記事内のCTAリンクです。Gumroad、問い合わせフォーム、無料PDFのURLは売上やリード獲得に直結します。Claude Codeに編集させる場合は、公開URL確認を完了条件に入れます。

2. 依存関係更新

パッケージ更新は、package.jsonだけでなくlockfile、ビルド結果、脆弱性レポートまで影響します。npm installpnpm addallowにするより、askに置いて、変更理由とロールバック手順を書かせます。

実務では、Claude Codeに「更新候補を3つに絞り、破壊的変更の有無とテストコマンドを表にして」と頼むほうが安全です。自動更新の速度より、レビューできる粒度のほうが重要です。

3. 認証・課金・分析タグ

ログイン、Stripe、Gumroad、広告タグ、メール送信先、Webhookは必ず承認ゲートに入れます。この領域では「コードが動く」だけでは不十分です。誰のデータが送られるか、失敗時に二重課金にならないか、ログに個人情報が残らないかを見ます。

特にCLAUDE_CODE_SKIP_PROMPT_HISTORY=1は、プロンプト履歴とセッショントランスクリプトをディスクに書かない設定です。機密性の高い一時セッションでは役立ちますが、チーム監査で「なぜその判断をしたか」を追いたい場合は逆効果になります。

4. チーム引き継ぎ

別の担当者へ引き継ぐときは、権限そのものよりも判断理由を残します。「何を許可したか」「何を止めたか」「どの確認が未完了か」がわかれば、次の担当者は同じ調査を繰り返さずに済みます。

Handoff note:
- Allowed today: Edit content files, run lint, run unit tests.
- Asked before: package changes, deploy, payment links, analytics tags.
- Denied: .env reads, arbitrary curl/wget, recursive delete.
- Evidence: npm run lint passed, git diff reviewed.
- Remaining risk: production URL has not been checked after deploy.

具体的な落とし穴

1つ目は、allowを広げすぎることです。Bash全体やPowerShell全体の自動許可は、便利な反面、境界がほぼ消えます。WindowsではPowerShellルールもPowerShell(Get-ChildItem *)のように書けますが、Remove-ItemInvoke-WebRequestの扱いは慎重にします。

2つ目は、URLをBashパターンだけで縛ろうとすることです。Bash(curl https://github.com *)のようなルールは、オプション、リダイレクト、変数、スペースの違いで抜けます。ネットワークを制限したいなら、curlwgetdenyに置き、必要な取得はWebFetch(domain:example.com)やhookで扱うほうが明確です。

3つ目は、ラッパーコマンドです。公式ドキュメントではtimeouttimeなど一部のwrapperは解析されますが、npxdocker execdevbox runmise execのような開発環境ランナーは同じ扱いではありません。Bash(devbox run *)を許可すると、その先で実行されるコマンドまで広く許す形になり得ます。

4つ目は、Read/Editのdenyを過信することです。Claude Codeの組み込みファイルツールや認識できるBash読み取りには効きますが、任意のNodeやPythonスクリプトが内部でファイルを開くケースまでOSレベルで止めるものではありません。機密ファイルを本当に隔離したい場合はsandboxやコンテナを併用します。

チームで使う依頼文

朝の最初のプロンプトは、実装依頼ではなく監査依頼にします。

Before changing files, audit Claude Code permissions for this repository.
Return:
1. allow rules that are safe for today's task
2. ask rules that should stay behind human approval
3. deny rules that protect secrets, deploys, and destructive commands
4. environment variables that affect logs or subprocess secrets
5. the smallest task you can complete with proof and rollback notes
Do not edit files until the audit is summarized.

この依頼文は、Claude Codeの行動を完全に制限するものではありません。制限はsettingsや権限UIで行います。ただし、最初に境界を言語化させると、レビューする側が「その作業なら編集してよい」「それは人間承認」と判断しやすくなります。

収益導線を壊さないためのCTA確認

このサイトのように記事から無料PDF、Gumroad商品、導入相談へつなげる構成では、権限監査はセキュリティだけでなく売上保護にも効きます。Claude Codeの基本操作をまだ固めていない場合は 無料チートシート から始めてください。チーム導入、CLAUDE.md、権限、hook、MCPまでまとめて整えたい場合は Setup Guide が近道です。運用設計まで一緒に詰めたい場合は 導入相談 へ進んでください。

実際に試した結果、朝の最初にgit status/permissions.claude/settings.local.json、監査スクリプトの4点を確認するだけで、作業後レビューの会話が短くなりました。特に効果があったのは、Gumroadリンクやデプロイ設定をaskに残したことです。Claude Codeの速度は落ちますが、売上導線や本番環境を触る変更で「なぜ許可したのか」を説明できるようになり、結果としてチームの承認が早くなりました。

#claude-code #permissions #security #setup #workflow #claude-md
無料

無料PDF: Claude Code はじめてのチートシート

まずは無料PDFで基本コマンドと最初の使い方をまとめて確認してください。登録後はそのままテンプレート集や導入相談にも進めます。

スパムは送りません。登録情報は厳重に管理します。

Claude Codeを仕事で使える形にしませんか?

無料PDFで基礎を固めたあと、すぐ使えるテンプレート集で試し、必要なら業務自動化や導入相談まで進められます。

Masa

この記事を書いた人

Masa

Claude Codeの実務活用、導入設計、収益導線改善を検証しているエンジニア。10言語の技術メディアを運営中。

PR

関連書籍・参考図書

この記事のテーマに関連する書籍を楽天ブックスで探せます。

※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。