Skip to content

permissions.denyルールがPreToolUseフックの許可決定を上書きできない問題を修正

原文(日本語に翻訳)

permissions.deny ルールが PreToolUse フックの permissionDecision: "ask" を上書きできない問題を修正。以前はフックが拒否を確認プロンプトにダウングレードできてしまっていた

原文(英語)

Fixed permissions.deny rules not overriding a PreToolUse hook's permissionDecision: "ask" — previously the hook could downgrade a deny into a prompt

概要

permissions.deny でツールの使用を明示的に拒否していても、PreToolUseフックが permissionDecision: "ask" を返すことで実質的に拒否が「確認プロンプト」にダウングレードされてしまうセキュリティ上の問題が修正されました。修正後は permissions.deny ルールが最優先され、フックの設定に関わらず拒否されます。

基本的な使い方

permissions.denyの設定(修正後は確実に機能)

json
// settings.json
{
  "permissions": {
    "deny": [
      "Bash(rm -rf *)",
      "Bash(sudo *)",
      "Write(/etc/*)"
    ]
  }
}

修正前:PreToolUseフックが permissionDecision: "ask" を返すと、上記の拒否ルールが無視されてプロンプトが表示されることがあった。

修正後:permissions.deny ルールは最優先され、フックの返り値に関わらず拒否される。

実践例

セキュリティポリシーの適用

json
// .claude/settings.json(プロジェクトレベル)
{
  "permissions": {
    "deny": [
      "Bash(curl * | bash)",
      "Bash(wget * | sh)",
      "Bash(npm publish*)",
      "Bash(git push --force*)"
    ]
  }
}
typescript
// hooks/pre-tool-use.ts(カスタムフック)
export default function preToolUse(tool: string, input: unknown) {
  // このフックが "ask" を返しても、
  // permissions.deny に一致するルールは無条件で拒否される(修正後)
  if (needsUserConfirmation(tool, input)) {
    return { permissionDecision: "ask" };
  }
  return { permissionDecision: "allow" };
}

チーム共有の安全設定

json
// 管理者が設定するチーム共有ポリシー(managed settings)
{
  "permissions": {
    "deny": [
      // 本番環境への直接デプロイを防止
      "Bash(kubectl apply * --namespace=production)",
      "Bash(terraform apply *)",
      // 機密ファイルへのアクセスを防止
      "Read(/etc/passwd)",
      "Read(~/.ssh/*)"
    ]
  }
}

修正後は、どんなフック設定があっても管理者が設定した deny ルールが確実に適用されます。

PreToolUseフックと組み合わせた適切な設計

typescript
// 修正後の推奨パターン:
// フックはpermissions.denyでカバーされていない細かい制御に使用

export default function preToolUse(tool: string, input: any) {
  // permissions.denyに書けない動的な条件
  if (tool === "Bash" && isExpensiveOperation(input.command)) {
    return { 
      permissionDecision: "ask",
      message: "この操作はコストが高い可能性があります。続けますか?"
    };
  }
  
  // permissions.denyに書くべき絶対拒否は settings.json で管理
  // フックではなく設定ファイルで管理することでポリシーが明確になる
  return { permissionDecision: "allow" };
}

権限決定の優先順位(修正後)

優先度設定動作
1(最高)permissions.deny無条件で拒否
2permissions.allow自動的に許可
3PreToolUseフックの返り値フックの判断に従う
4(最低)デフォルトユーザーに確認

注意点

  • セキュリティへの影響: この修正でセキュリティポリシーの適用がより確実になります。permissions.deny で設定したルールが実際に機能していることを確認してください
  • フックの役割の明確化: フックは permissions.deny でカバーできない細かな制御に使用し、絶対に拒否したいものは permissions.deny で設定するのがベストプラクティスです
  • 既存フックの影響: permissionDecision: "ask" を返すフックがあり、permissions.deny も設定している場合、修正後は deny ルールが常に優先されます

関連情報