클로드 코드 권한 설정: 팝업 없이 안전하게 쓰기

클로드 코드를 쓰다 보면 가장 자주 마주치는 것이 “이 명령어를 실행해도 될까요?”라는 권한 요청 팝업입니다. 처음에는 안전장치로 느껴지지만 매번 답하다 보면 꽤 성가시죠. 이 글에서는 클로드 코드의 권한 시스템을 속속들이 파헤쳐서 안전하면서도 흐름이 끊기지 않는 환경을 만드는 방법을 알아보겠습니다.

권한 시스템의 기본 구조

클로드 코드는 도구 종류에 따라 세 단계의 기본 권한 정책을 적용합니다.

도구 유형예시승인 필요”다시 묻지 않기” 범위
읽기 전용파일 읽기, Grep, Glob없음
Bash 명령어셸 실행있음프로젝트 디렉토리 + 명령어 단위로 영구
파일 수정Edit, Write있음세션 종료 시까지

읽기 전용 도구는 별다른 확인 없이 바로 사용할 수 있고, Bash 명령어는 한 번 허용하면 같은 프로젝트에서 같은 명령어에 한해 영구적으로 허용됩니다. 파일 수정은 세션이 끝나면 다시 물어보죠.

이 기본 정책만으로도 기본적인 보호는 되지만 프로젝트마다 쓰는 명령어가 다르고 팀마다 보안 요구사항이 다릅니다. 그래서 settings.jsonpermissions 설정으로 이 동작을 세밀하게 제어할 수 있어요.

allow, deny, ask 규칙

권한 규칙은 크게 세 가지로 나뉩니다.

{
  "permissions": {
    "allow": ["자동 허용할 도구와 패턴"],
    "ask": ["매번 확인을 거칠 도구와 패턴"],
    "deny": ["무조건 차단할 도구와 패턴"]
  }
}

평가 순서는 deny → ask → allow입니다. deny에 해당하는 규칙이 있으면 allow에도 있더라도 무조건 차단돼요. 보안상 차단 규칙이 항상 우선한다는 뜻이죠.

현재 적용 중인 권한 규칙은 클로드 코드 안에서 /permissions 명령으로 확인할 수 있습니다. 어떤 규칙이 어느 설정 파일에서 왔는지도 볼 수 있어서 디버깅할 때 유용해요.

설정 파일의 계층 구조

권한 설정은 여러 레벨의 설정 파일에 분산됩니다. 우선순위가 높은 설정이 낮은 설정을 덮어쓰는 구조예요.

우선순위범위파일 위치
1 (최고)관리자OS별 시스템 경로
2CLI 인자명령줄 실행 시
3로컬 프로젝트.claude/settings.local.json
4프로젝트.claude/settings.json
5 (최저)사용자~/.claude/settings.json

예를 들어 사용자 설정에서 Bash(rm -rf *)를 허용했더라도 프로젝트 설정에서 이를 deny에 넣으면 차단이 적용됩니다.

실무에서 권한을 배치하는 방법은 이렇습니다. 사용자 설정(~/.claude/settings.json)에는 git status, --version, --help처럼 어디서든 안전하게 쓰는 명령어를 허용해두고, 프로젝트 설정(.claude/settings.json)에는 팀에서 합의한 빌드·테스트 명령어 허용과 민감 파일 차단 규칙을 넣습니다. 로컬 프로젝트 설정(.claude/settings.local.json)은 .gitignore에 포함되니까 팀 설정 위에 자기만의 추가 규칙을 올리면 돼요.

권한 외의 설정 옵션(모델 선택, 언어, 환경 변수 등)이 궁금하다면 클로드 코드 설정 가이드를 참고하세요.

권한 모드

defaultMode 옵션으로 클로드 코드의 기본 동작 방식을 정할 수 있습니다.

{
  "permissions": {
    "defaultMode": "acceptEdits"
  }
}
  • default — 처음 사용하는 도구마다 허용 여부를 물어봅니다
  • acceptEdits — 파일 편집은 자동 허용합니다. Shift+Tab으로 전환할 수 있어요
  • plan — 코드 분석만 가능하고 파일 수정이나 명령어 실행은 불가합니다
  • delegate — 에이전트 팀 리더 전용 모드입니다. 구현은 팀원 에이전트에게 위임하고 본인은 조율만 합니다
  • dontAsk — allow 목록에 없으면 묻지 않고 자동 거부합니다
  • bypassPermissions — 모든 권한 확인을 건너뜁니다. 컨테이너나 VM 같은 격리 환경에서만 써야 해요

보통 acceptEdits가 가장 쓸 만합니다. 코드 편집은 자동으로 허용하되 셸 명령어 실행은 여전히 확인을 거치니까 편하면서도 안전하거든요.

CI/CD 환경에서는 dontAsk이 적합합니다. 사람이 승인 팝업에 답할 수 없으니 allow 목록에 있는 것만 실행하고 나머지는 조용히 거부하는 거죠.

Bash 명령어 권한

Bash 권한 규칙은 Bash(패턴) 형식으로 작성하고 glob 패턴(*)을 지원합니다.

{
  "permissions": {
    "allow": [
      "Bash(npm run build)",
      "Bash(npm run test *)",
      "Bash(git commit *)",
      "Bash(git * main)",
      "Bash(* --version)",
      "Bash(* --help *)"
    ],
    "deny": [
      "Bash(rm -rf *)",
      "Bash(sudo *)",
      "Bash(git push *)"
    ]
  }
}

와일드카드 *는 명령어의 어느 위치에든 올 수 있습니다. Bash(git * main)git checkout main, git merge main 같은 명령어를 모두 매칭하죠.

여기서 주의할 점이 있습니다. * 앞에 공백이 있으면 단어 경계를 인식합니다. Bash(ls *)ls -la와 매칭되지만 lsof와는 매칭되지 않아요. ls로 시작하는 모든 명령어를 매칭하고 싶다면 Bash(ls*)처럼 공백 없이 작성해야 합니다.

참고로 이전에는 Bash(npm run:*) 같은 콜론-별표(:*) 문법도 사용됐지만 현재는 deprecated되었습니다. 기존에 이 문법을 쓰고 있었다면 Bash(npm run *) 형태의 스페이스-별표 문법으로 바꿔주세요.

클로드 코드는 셸 연산자도 이해합니다. Bash(safe-cmd *)safe-cmd && malicious-cmd 같은 명령어 체이닝에는 매칭되지 않아요. 단순 문자열 매칭이 아니라 셸 구문을 파싱하기 때문에 체이닝을 통한 우회를 막아줍니다.

Bash 패턴의 한계

Bash 권한 패턴으로 명령어 인자까지 제한하는 건 완벽하지 않습니다. 예를 들어 Bash(curl http://github.com/ *)로 GitHub URL만 허용하려고 해도 이런 변형을 막지 못해요.

# 옵션이 URL 앞에 오는 경우
curl -X GET http://github.com/...

# 프로토콜이 다른 경우
curl https://github.com/...

# 리다이렉트를 이용한 우회
curl -L http://bit.ly/xyz

# 변수를 이용한 우회
URL=http://evil.com && curl $URL

URL을 제한하고 싶다면 Bash에서 curl, wget 같은 네트워크 도구를 deny로 막고 대신 WebFetch(domain:github.com) 규칙으로 특정 도메인만 여는 것이 안전합니다.

파일 읽기·편집 권한

ReadEdit 규칙은 gitignore 스펙을 따르는 경로 패턴을 사용합니다. Edit 규칙은 파일을 수정하는 모든 내장 도구에 적용되고, Read 규칙은 Grep이나 Glob 같은 읽기 도구에도 적용됩니다.

패턴의미예시
//경로파일 시스템 절대 경로Read(//Users/alice/secrets/**)
~/경로홈 디렉토리 기준Read(~/Documents/*.pdf)
/경로설정 파일 위치 기준Edit(/src/**/*.ts)
경로현재 디렉토리 기준Read(*.env)

여기서 흔히 하는 실수가 있습니다. /Users/alice/file은 절대 경로가 아니라 설정 파일 위치 기준의 상대 경로입니다. 절대 경로를 쓰려면 반드시 슬래시 두 개(//Users/alice/file)로 시작해야 해요.

gitignore 패턴에서 *은 단일 디렉토리 내 파일만 매칭하고 **은 재귀적으로 하위 디렉토리까지 매칭합니다.

{
  "permissions": {
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)",
      "Read(**/*.pem)",
      "Read(**/*.key)"
    ]
  }
}

.env 파일, 시크릿 디렉토리, SSL 인증서 같은 민감한 파일은 이렇게 deny에 넣어두면 실수로 읽히는 것을 막을 수 있습니다.

WebFetch 권한

WebFetch는 도메인 기반으로 제어합니다.

{
  "permissions": {
    "allow": [
      "WebFetch(domain:docs.anthropic.com)",
      "WebFetch(domain:developer.mozilla.org)"
    ],
    "deny": [
      "WebFetch"
    ]
  }
}

특정 도메인만 허용하고 나머지는 차단하는 화이트리스트 방식이 안전합니다. 다만 WebFetch를 막았다고 네트워크 접근이 완전히 차단되는 건 아니에요. Bash가 허용돼 있으면 curl이나 wget으로 여전히 외부에 접근할 수 있거든요. 네트워크를 확실히 제한하려면 Bash에서 네트워크 도구를 deny로 막거나 뒤에서 다룰 샌드박스를 함께 쓰는 것이 좋습니다.

MCP 도구 권한

외부 MCP 서버의 도구는 mcp__서버이름__도구이름 형식으로 지정합니다.

{
  "permissions": {
    "allow": [
      "mcp__github__create_issue",
      "mcp__github__list_pull_requests"
    ],
    "deny": [
      "mcp__github__delete_repository"
    ]
  }
}

서버 단위로 한 번에 제어할 수도 있습니다. mcp__puppeteer는 puppeteer 서버의 모든 도구를 매칭하고, mcp__puppeteer__*도 같은 의미예요.

서브 에이전트 권한

클로드 코드의 서브 에이전트도 권한으로 제어할 수 있습니다. Task(에이전트이름) 형식이에요.

{
  "permissions": {
    "deny": [
      "Task(Explore)",
      "Task(Plan)"
    ]
  }
}

특정 서브 에이전트를 비활성화할 때 유용하죠. CLI에서 --disallowedTools 플래그로도 같은 효과를 낼 수 있고요.

추가 디렉토리 접근

기본적으로 클로드 코드는 실행된 디렉토리만 접근할 수 있습니다. 다른 디렉토리의 파일도 다뤄야 한다면 세 가지 방법이 있어요.

우선 설정 파일에 additionalDirectories를 넣어두면 영구적으로 적용됩니다.

{
  "permissions": {
    "additionalDirectories": ["../shared-lib/", "../docs/"]
  }
}

또는 일회성으로 필요하다면 실행할 때 --add-dir <경로> CLI 인자를 쓸 수 있고, 세션 중에 /add-dir 명령으로 추가할 수도 있어요. 추가된 디렉토리의 파일은 원래 작업 디렉토리와 동일한 권한 규칙을 따릅니다.

모노레포 환경이나 여러 프로젝트를 오가며 작업할 때 유용합니다.

샌드박스와 권한의 관계

클로드 코드 설정 가이드에서도 다뤘지만 샌드박스는 권한과 함께 쓸 때 진가를 발휘합니다. 두 시스템은 서로 다른 계층에서 보안을 담당해요.

권한(Permissions)은 클로드 코드가 어떤 도구를 쓸 수 있고 어떤 파일이나 도메인에 접근할 수 있는지를 제어합니다. Bash, Read, Edit, WebFetch, MCP 등 모든 도구에 적용되죠. 반면 샌드박스(Sandbox)는 OS 레벨에서 Bash 명령어의 파일 시스템과 네트워크 접근을 격리합니다. Bash 명령어와 그 자식 프로세스에만 적용돼요.

이 둘을 함께 쓰면 다층 방어가 됩니다. 권한 deny 규칙은 Claude가 제한된 리소스에 접근하려는 시도 자체를 막고, 샌드박스는 프롬프트 인젝션 같은 공격으로 Claude의 판단이 우회되더라도 Bash 명령어가 정해진 경계 밖으로 나가지 못하게 막아줍니다.

{
  "permissions": {
    "deny": ["Bash(curl *)", "Bash(wget *)"]
  },
  "sandbox": {
    "enabled": true,
    "autoAllowBashIfSandboxed": true,
    "network": {
      "allowedDomains": ["github.com", "*.npmjs.org"]
    }
  }
}

autoAllowBashIfSandboxedtrue로 설정하면 샌드박스 안에서 실행되는 Bash 명령은 별도의 권한 확인 없이 자동 허용됩니다. 샌드박스가 시스템을 보호해주니까 권한 팝업 피로를 줄이면서도 안전한 거죠.

Hooks로 권한 확장하기

클로드 코드 Hooks를 사용하면 기본 권한 시스템을 넘어선 커스텀 로직을 적용할 수 있습니다. PreToolUse 훅은 Claude가 도구를 호출하기 전에 실행되는데, 훅의 종료 코드로 도구 호출을 승인하거나 거부할 수 있어요.

예를 들어 Bash의 glob 패턴 매칭으로는 한계가 있는 URL 검증을 훅에서 처리할 수 있습니다.

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "jq -re '.tool_input.command | test(\"curl|wget\") | not' || exit 2"
          }
        ]
      }
    ]
  }
}

이 훅은 Bash 명령어에 curl이나 wget이 포함되면 종료 코드 2를 반환해서 실행을 차단합니다. 정규식이나 외부 검증 스크립트를 적용하면 glob 패턴보다 훨씬 정밀한 권한 제어를 구현할 수 있죠.

관리자 설정 (기업용)

기업 환경에서는 IT 관리자가 시스템 레벨의 설정 파일로 조직 전체 정책을 강제할 수 있습니다. 이 설정은 사용자나 프로젝트 설정으로는 절대 덮어쓸 수 없어요.

OS경로
macOS/Library/Application Support/ClaudeCode/managed-settings.json
Linux/WSL/etc/claude-code/managed-settings.json
WindowsC:\Program Files\ClaudeCode\managed-settings.json

관리자 설정에서만 쓸 수 있는 옵션이 몇 가지 있어요.

  • disableBypassPermissionsMode"disable"로 설정하면 bypassPermissions 모드와 --dangerously-skip-permissions 플래그를 완전히 차단합니다
  • allowManagedPermissionRulesOnlytrue로 설정하면 사용자와 프로젝트 설정에서 allow, ask, deny 규칙 정의가 불가능해집니다. 관리자 설정의 규칙만 적용돼요
  • allowManagedHooksOnlytrue로 설정하면 사용자, 프로젝트, 플러그인 훅을 차단하고 관리자 훅과 SDK 훅만 허용합니다

보안 감사를 받아야 하거나 규제 산업에서 일한다면 이 옵션들이 유용할 거예요.

실전 예시: 상황별 추천 설정

개인 개발자

혼자 개발하는 경우라면 편하게 쓰는 데 초점을 둔 설정이 좋습니다.

~/.claude/settings.json
{
  "permissions": {
    "allow": [
      "Bash(npm run *)",
      "Bash(bun run *)",
      "Bash(git add *)",
      "Bash(git commit *)",
      "Bash(git diff *)",
      "Bash(git log *)",
      "Bash(git status)",
      "Bash(* --version)",
      "Bash(* --help *)"
    ],
    "deny": [
      "Bash(rm -rf *)",
      "Bash(sudo *)"
    ],
    "defaultMode": "acceptEdits"
  }
}

자주 쓰는 명령어는 allow에 넣어서 팝업을 줄이고 위험한 명령어만 deny로 막는 전략이에요. acceptEdits 모드로 파일 수정도 자동 허용하면 작업 흐름이 훨씬 매끄럽습니다.

팀 프로젝트

팀에서 공유하는 설정은 보안에 좀 더 신경 써야 합니다.

.claude/settings.json
{
  "permissions": {
    "allow": [
      "Bash(npm run build)",
      "Bash(npm run test *)",
      "Bash(npm run lint)",
      "Bash(npx prettier *)"
    ],
    "deny": [
      "Bash(rm -rf *)",
      "Bash(sudo *)",
      "Bash(curl *)",
      "Bash(wget *)",
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)",
      "Read(**/*.pem)",
      "Read(**/*.key)"
    ]
  }
}

민감한 파일에 대한 접근을 막고 외부 네트워크 요청도 제한해서 데이터가 새어나가지 않게 합니다. 이 파일을 Git에 커밋하면 팀원 전체에 동일한 규칙이 적용되죠.

CI/CD 환경

클로드 코드 GitHub Actions처럼 자동화 환경에서는 사람의 승인 없이 실행되므로 필요한 권한만 정확히 열어둬야 합니다.

.claude/settings.json
{
  "permissions": {
    "allow": [
      "Bash(npm run build)",
      "Bash(npm run test *)",
      "Bash(npm run lint)",
      "Bash(git add *)",
      "Bash(git commit *)",
      "Bash(git push *)"
    ],
    "deny": [
      "Bash(rm -rf *)",
      "Bash(sudo *)"
    ],
    "defaultMode": "dontAsk"
  }
}

dontAsk 모드를 쓰면 allow에 있는 명령어만 자동 실행되고 나머지는 묻지 않고 거부합니다. CI 환경에서는 묻더라도 답할 사람이 없으니까요.

마치며

클로드 코드의 권한 시스템은 단순한 허용/차단을 넘어 도구별 패턴 매칭, 계층적 설정 파일, 다양한 실행 모드, 샌드박스 연동까지 꽤 정교합니다.

처음에는 사용자 설정에 자주 쓰는 명령어 허용 규칙만 넣어두는 것으로 충분합니다. 팀 프로젝트에서 일관된 규칙이 필요해지면 프로젝트 설정을 추가하고 보안이 중요한 환경에서는 샌드박스와 deny 규칙을 강화하면 돼요.

클로드 코드 설정 가이드의 모델 선택이나 환경 변수 같은 옵션을 권한과 조합하고 클로드 코드 Hooks로 커스텀 검증 로직까지 더하면 안전하면서도 흐름이 끊기지 않는 AI 코딩 환경을 만들 수 있습니다. 권한 시스템과 함께 OS 레벨 격리까지 적용하고 싶다면 클로드 코드 샌드박스를 참고하세요.

This work is licensed under CC BY 4.0 CC BY

Discord