권한 시스템

Claude Code가 도구 실행 여부를 결정하는 방법 — 거부 규칙부터 AI 분류기까지.

01

개요

Claude Code의 권한 시스템은 모든 도구 호출이 사용자의 의도와 보안 정책에 부합하는지 검증하는 핵심 게이트키퍼입니다. 단순한 허용/거부 목록이 아닌, 다단계 결정 파이프라인을 통해 규칙 매칭, 모드 기반 변환, AI 분류기까지 계층적으로 동작합니다.

다루는 소스 파일: permissions/ 디렉토리 — permissionCheck.ts, permissionRules.ts, permissionModes.ts, autoModeClassifier.ts

권한 시스템의 핵심 원칙:

02

결정 파이프라인 3단계

모든 도구 호출은 다음 세 단계를 순서대로 통과합니다:

단계 1 — 규칙 & 안전 검사

첫 번째로 거부(deny) 규칙을 평가합니다. 거부 규칙에 매칭되면 즉시 차단되며, 어떤 모드나 허용 규칙으로도 이를 되돌릴 수 없습니다. 이후 .git/.claude/ 디렉토리에 대한 안전 검사, requiresUserInteraction 플래그, 콘텐츠 기반 ask 규칙도 이 단계에서 평가됩니다.

// permissionCheck.ts — 거부 규칙이 항상 최우선
const denyMatch = rules.deny.find(r => matchesRule(r, toolCall))
if (denyMatch) {
  return { decision: 'deny', reason: denyMatch.reason }
}

// 안전 검사: .git/ 및 .claude/ 쓰기 보호
if (isProtectedPath(toolCall.path)) {
  return { decision: 'ask', reason: 'protected directory' }
}

단계 2 — 모드 & 허용 규칙

거부되지 않은 호출은 현재 권한 모드와 허용(allow) 규칙을 기준으로 평가됩니다. 허용 규칙에 매칭되면 프롬프트 없이 실행됩니다. 매칭되지 않으면 모드에 따라 ask(사용자에게 질문) 또는 allow(자동 허용)로 분류됩니다.

단계 3 — 모드 변환

최종 결정이 ask인 경우, 현재 모드에 따라 변환됩니다. 예를 들어 bypassPermissions 모드에서는 askallow로 변환되고, dontAsk 모드에서는 askdeny로 변환됩니다.

주의사항

bypassPermissions도 bypass 불가능한 4가지가 있습니다: 거부 규칙, requiresUserInteraction 플래그, 콘텐츠 기반 ask 규칙, .git/.claude/ 안전 검사. 이 4가지는 모든 모드에서 항상 사용자에게 프롬프트되거나 거부됩니다.

03

5가지 권한 모드

Claude Code는 5가지 권한 모드를 지원하며, 각 모드는 ask 결정을 다르게 변환합니다:

// permissionModes.ts — 모드별 ask 변환
function transformAskDecision(mode: PermissionMode): Decision {
  switch (mode) {
    case 'bypassPermissions': return 'allow'   // ask → allow
    case 'dontAsk':           return 'deny'    // ask → deny
    case 'default':           return 'ask'     // ask → ask (프롬프트)
    // ...
  }
}
딥 다이브 — dontAsk vs bypassPermissions

두 모드 모두 사용자 프롬프트를 제거하지만 정반대 방향으로 동작합니다. bypassPermissions는 "묻지 않고 허용"이고, dontAsk는 "묻지 않고 거부"입니다. CI/자동화 환경에서는 dontAsk가 안전한 기본값입니다 — 허용 규칙에 명시적으로 등록되지 않은 도구 호출은 자동으로 차단됩니다.

04

규칙 매칭

규칙은 세 가지 매칭 방식을 지원합니다:

// permissionRules.ts — 규칙 매칭 로직
function matchesRule(rule: Rule, toolCall: ToolCall): boolean {
  const pattern = rule.pattern
  if (pattern.includes('*')) {
    // 와일드카드 매칭: Bash(npm:*) → "npm"으로 시작하는 모든 것
    return globMatch(toolCall.input, pattern)
  }
  // 정확 매칭
  return toolCall.input === pattern
}

Bash(npm:*)는 와일드카드 매칭의 예시입니다. npm install, npm test, npm run buildnpm으로 시작하는 모든 Bash 명령어에 매칭됩니다.

05

규칙 소스 & 우선순위 (8개 소스)

규칙은 8개의 소스에서 로드되며, 각 소스는 우선순위가 다릅니다. 우선순위가 높은 소스의 규칙이 낮은 소스를 덮어씁니다:

  1. 하드코딩된 안전 규칙 — 코드에 내장된 최우선순위 보호
  2. 정책 설정 (remote) — 원격 관리 설정
  3. 정책 설정 (MDM) — 모바일 디바이스 관리
  4. 정책 설정 (file) — 파일 기반 정책
  5. CLI 플래그--allowedTools, --disallowedTools
  6. 사용자 설정~/.claude/settings.json
  7. 프로젝트 설정.claude/settings.json
  8. 로컬 설정.claude/settings.local.json

거부 규칙은 소스에 관계없이 항상 허용 규칙보다 우선합니다. 같은 도구에 대해 상위 소스에서 거부하고 하위 소스에서 허용해도 거부가 승리합니다.

딥 다이브 — 섀도 규칙 감지

섀도 규칙이란 더 높은 우선순위의 규칙에 의해 실질적으로 무효화된 규칙입니다. 예를 들어, 사용자 설정에서 allow: ["Bash(npm:*)"]를 설정했지만 정책 설정에서 deny: ["Bash(npm:*)"]가 있으면, 사용자의 허용 규칙은 섀도 처리됩니다. 권한 설명기(Permission Explainer)는 이러한 섀도 관계를 시각적으로 보여줍니다.

06

자동 모드 & AI 분류기

자동(auto) 모드는 AI 분류기를 사용하여 도구 호출의 안전성을 판단합니다. 안전 도구 허용 목록에 있는 도구는 분류 없이 즉시 허용되고, 그 외의 도구는 분류기가 평가합니다.

안전 도구 허용 목록

읽기 전용 도구(Read, Glob, Grep 등)는 기본적으로 안전한 것으로 분류되어 AI 분류기 호출 없이 자동 허용됩니다.

거부 추적 메커니즘

AI 분류기의 안전장치로, 연속 거부 횟수와 총 거부 횟수를 추적합니다:

// autoModeClassifier.ts — 거부 추적
let consecutiveDenials = 0
let totalDenials = 0

if (consecutiveDenials >= 3 || totalDenials >= 20) {
  // 자동 허용 대신 사용자에게 프롬프트
  return { decision: 'ask', fallback: true }
}
딥 다이브 — 권한 설명기

권한 설명기(Permission Explainer)는 특정 도구 호출에 대해 어떤 규칙이 어떤 소스에서 매칭되었는지, 최종 결정이 어떻게 도출되었는지를 단계별로 설명합니다. 디버깅 시 왜 특정 도구가 차단되거나 허용되었는지 추적하는 데 필수적인 도구입니다. 섀도 규칙도 명시적으로 표시하여 규칙 충돌의 원인을 빠르게 파악할 수 있습니다.

07

핵심 요약

핵심 포인트

  • 권한 결정은 3단계 파이프라인을 통해 이루어집니다: 규칙 & 안전 검사 → 모드 & 허용 규칙 → 모드 변환
  • 거부(deny) 규칙은 항상 최우선으로 평가되며, 어떤 모드나 허용 규칙으로도 되돌릴 수 없습니다
  • bypassPermissions 모드조차 우회할 수 없는 4가지: 거부 규칙, requiresUserInteraction, 콘텐츠 ask 규칙, .git/.claude 안전 검사
  • 5가지 모드(default, plan, acceptEdits, bypassPermissions, dontAsk/auto)가 ask 결정을 다르게 변환합니다
  • 규칙 매칭은 정확, 접두사(레거시), 와일드카드 세 가지 방식을 지원합니다
  • 8개 소스에서 규칙이 로드되며, 하드코딩 안전 규칙이 최우선순위를 가집니다
  • 자동 모드의 AI 분류기는 3연속 또는 20총 거부 시 사용자 프롬프트로 폴백합니다
  • 권한 설명기로 규칙 매칭 과정과 섀도 규칙을 디버깅할 수 있습니다
08

지식 확인

퀴즈 — 5문제

Q1. deny 규칙에 Bash(*)가 있고 allow 규칙에 Bash(ls:*)가 있을 때, ls -la 실행 시 결과는?

  • A) 허용 — allow 규칙에 매칭되므로
  • B) 거부 — 거부 규칙이 허용 규칙보다 먼저 평가됨
  • C) 사용자에게 질문
  • D) 소스 우선순위에 따라 다름
거부(deny) 규칙은 파이프라인의 첫 번째 단계에서 평가됩니다. Bash(*)는 모든 Bash 호출에 매칭되므로, allow 규칙에 관계없이 즉시 거부됩니다. 거부 규칙은 항상 최우선입니다.

Q2. bypassPermissions 모드에서도 사용자에게 프롬프트되는 것은?

  • A) git commit 실행
  • B) src/main.ts 파일 쓰기
  • C) .git/hooks/pre-commit 파일 쓰기
  • D) FileRead 도구 호출
.git/ 디렉토리는 안전 검사 대상입니다. bypassPermissions 모드라도 .git/이나 .claude/ 디렉토리에 대한 쓰기는 항상 사용자에게 프롬프트됩니다. 이는 리포지토리 무결성을 보호하기 위한 불가침 안전 장치입니다.

Q3. 자동 모드 AI 분류기가 3연속 거부를 기록한 후, 4번째 도구 호출 시 동작은?

  • A) 세션 중단
  • B) 자동 허용
  • C) 사용자 권한 프롬프트로 폴백
  • D) 분류기 비활성화
3연속 거부 또는 20총 거부 임계값에 도달하면, 자동 모드는 AI 분류기의 자동 결정을 중단하고 사용자에게 직접 권한을 프롬프트합니다. 이는 분류기 오류가 누적되어 작업이 완전히 차단되는 것을 방지하는 안전장치입니다.

Q4. Bash(npm:*) 규칙의 매칭 타입은?

  • A) 와일드카드
  • B) 접두사 (레거시)
  • C) 정확
  • D) 정규식
Bash(npm:*)에서 *는 와일드카드 글로브 패턴입니다. npm 뒤에 오는 모든 문자열에 매칭됩니다. 와일드카드 매칭은 정확 매칭과 달리 패턴 기반으로 유연한 규칙 정의를 가능하게 합니다.

Q5. dontAskbypassPermissions의 차이는?

  • A) dontAsk는 모든 도구를 허용
  • B) dontAsk는 ask → deny 변환, bypassPermissions는 ask → allow 변환
  • C) 동일한 동작
  • D) dontAsk는 안전 검사를 건너뜀
두 모드 모두 사용자 프롬프트를 제거하지만, 방향이 정반대입니다. bypassPermissions는 "묻지 않고 허용" (ask → allow), dontAsk는 "묻지 않고 거부" (ask → deny)로 변환합니다. CI 환경에서는 dontAsk + 명시적 allow 규칙 조합이 안전한 패턴입니다.
0 / 5