Claude Code 권한·네트워크 허용, 프로젝트에서 어떻게 좁히나

Claude Code 권한 설정으로 프로젝트에서 도구·네트워크를 좁히려면, 공유 규칙은 .claude/settings.jsonpermissions.allow / ask / deny에 두고, 도메인은 WebFetch(domain:…)와(필요 시) sandbox.network.allowedDomains·deniedDomains로 맞춥니다. 규칙 평가는 deny → ask → allow 순입니다.

이 글은 공식 Configure permissions·Settings 문서를 따라 설정 파일 위치, 허용·거부 목록, Cursor rules와의 맞춤만 다룹니다. 프로젝트 설정 전반 튜토리얼·요금은 다루지 않습니다.

설정 파일은 어디?

한 줄 답: 팀 공유는 .claude/settings.json, 개인 예외는 .claude/settings.local.json, 전역 기본은 ~/.claude/settings.json입니다.

공식 Settings 문서는 범위를 네 층으로 나눕니다.

  • Shared project: .claude/settings.json — 레포에 커밋해 팀 권한·훅을 공유합니다.
  • Project local: .claude/settings.local.json — 본인만. “Yes, and don’t ask again”으로 저장한 Bash·WebFetch 승인이 여기에 쌓입니다.
  • User: ~/.claude/settings.json — 모든 프로젝트의 개인 기본.
  • Managed: 조직 managed-settings.json 등 — 사용자가 덮어쓸 수 없습니다.

permissions.allowadditionalDirectories는 워크스페이스 신뢰(trust) 후에만 적용됩니다. deny·ask는 제한만 하므로 신뢰 전에도 바로 적용됩니다. 목록형 키(permissions.allow 등)는 여러 파일에 있으면 병합되고, deny가 어느 스코프에 있어도 allow로 풀 수 없습니다.

허용 목록은 어떻게?

한 줄 답: Tool 또는 Tool(specifier) 규칙을 allow·ask·deny에 넣고, 네트워크는 WebFetch(domain:…)와 Bash deny·sandbox 도메인 목록을 함께 씁니다.

규칙 예:

{
  "permissions": {
    "allow": [
      "Bash(npm run lint)",
      "Bash(npm run test *)",
      "WebFetch(domain:docs.example.com)"
    ],
    "ask": [
      "Bash(git push *)"
    ],
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Bash(curl *)",
      "Bash(wget *)",
      "WebFetch(domain:*.internal.example)"
    ]
  }
}

핵심 계약은 다음과 같습니다.

  • 평가 순서: deny → ask → allow. 좁은 allow가 넓은 deny를 뚫지 않습니다.
  • Bash *: 접두·중간·접미 와일드카드. compound(&& 등)는 서브커맨드마다 따로 맞춥니다.
  • WebFetch: WebFetch(domain:host)로 호스트를 좁힙니다. 단독 WebFetch deny는 도구를 제거하고, WebFetch(domain:*)는 도메인 단위로 거절하며 sandbox 도메인 목록에도 영향을 줍니다.
  • 네트워크 우회: Bash에 curl/wget이 열려 있으면 WebFetch만으로 네트워크를 막지 못합니다. 문서가 권하는 조합은 Bash 네트워크 도구 deny + WebFetch 도메인 allow(+ sandbox allowlist)입니다.

샌드박스를 켜면 sandbox.network.allowedDomains / deniedDomains가 Bash 쪽 호스트를 OS 수준으로 제한합니다. strictAllowlist: true는 user·managed·CLI --settings에서만 효과가 있고, 레포 settings.json에 넣어도 적용되지 않습니다.

세션 중에는 /permissions로 규칙 출처를 확인하고 추가·삭제할 수 있습니다.

Cursor rules와 맞추려면?

한 줄 답: Cursor rules·CLAUDE.md는 “무엇을 하려는지”를 말하고, Claude Code permissions는 “무엇을 실행해도 되는지”를 강제합니다. 문구를 맞춰도 권한 파일에 deny가 없으면 막히지 않습니다.

역할을 나누면 충돌이 줄어듭니다.

어디에역할
의도·스타일CLAUDE.md, Cursor rules/AGENTS.md빌드 명령, 금지 관행, 리뷰 기준을 설명
강제 경계.claude/settings.json permissions도구·경로·도메인을 허용/질문/거부
런타임 가드PreToolUse hooks (Claude) / Hooks (Cursor)규칙으로 못 잡는 예외를 스크립트로 차단

실무 맞춤 예:

  1. 문서·이슈 트래커 도메인만 WebFetch(domain:…) allow.
  2. 시크릿은 Read(./.env*) deny — Cursor .cursorignore와 경로를 맞춥니다.
  3. npm test·npm run lint만 Bash allow — Cursor hooks의 포맷/테스트 가드와 같은 명령을 씁니다.
  4. “프로덕션에 curl 금지”를 rules에만 쓰지 말고 Bash(curl *) deny(+ sandbox)까지 넣습니다.

규칙은 모델이 아니라 Claude Code 런타임이 강제합니다. 프롬프트나 CLAUDE.md만으로는 permissions를 바꾸지 못합니다.

마무리

프로젝트에서 권한·네트워크를 좁히려면 ① 공유 파일(.claude/settings.json) → ② allow/ask/deny·WebFetch 도메인 → ③ Cursor rules와 의도만 맞추고 강제 경계는 permissions 순으로 잡습니다. 상세 문법과 sandbox 키는 Configure permissions·Settings를 기준으로 확인하시기 바랍니다.

출처