본문으로 건너뛰기
테마
폰트
크기
A A

Permissions — 도구·파일 접근 권한 정밀 제어

에이전트가 어떤 도구를, 어떤 파일·명령에 대해 사용할 수 있는지 한 줄짜리 패턴으로 정의하는 방법입니다. settings.jsonpermissions.allow·permissions.deny 두 배열로 통제하며, Glob 패턴과 도구별 인자 형식을 알면 거의 모든 시나리오를 표현할 수 있습니다.

먼저 알아둘 것 — Antigravity 공식 시스템은 별도 페이지입니다.

이 페이지의 permissions.allow / permissions.deny JSON 형식은 Claude Code 등 다른 에이전트의 표기법입니다. Antigravity v1.22.2(2026-04-08)부터는 Allow / Ask / Deny 3계층 통합 권한 시스템이 도입되어 GUI 중심으로 동작합니다.

Antigravity 사용자는 먼저 Unified Permissions (통합 권한) 페이지를 보고, 본 페이지는 Claude Code 호환 패턴 레퍼런스로 활용하세요.

이 페이지의 목적: Allowlist·Denylist의 개념적 설명은 Harness Engineering — 보안 레이어에 있습니다. 이 페이지는 Claude Code 스타일의 패턴 작성법에 초점을 맞춘 실전 레퍼런스입니다.

1. 왜 권한 설정이 필요한가? #

에이전트는 기본적으로 모든 도구·파일에 접근할 수 있습니다. 이 상태로 자율적으로 동작시키면 다음과 같은 사고가 발생합니다.

  • 비밀 노출 — 에이전트가 실수로 .env 파일을 읽어 콘텐츠가 컨텍스트에 들어가고, 응답·로그에 유출.
  • 의도치 않은 파괴git reset --hardrm -rf를 자동 실행해 작업 손실.
  • 스코프 이탈 — 한 프로젝트 작업 중 다른 디렉터리(~/.ssh 등)를 건드림.
  • 매번 반복되는 확인 프롬프트 — 무한정 "이 도구를 실행할까요?"가 떠 흐름이 끊어짐.

권한 설정은 이 두 양 끝(완전 자유 vs 매번 확인)의 중간 지점을 잡아주는 도구입니다. 안전한 작업은 자동으로, 위험한 작업은 차단이라는 원칙을 한 번에 정의하고 재사용합니다.

한 줄 비유
권한 설정은 회사의 출입증 정책입니다. 누구나 1층 카페는 자유롭게(allow), 사무실 층은 사원증으로(ask), 서버실은 관리자만(deny) 출입할 수 있도록 한 번에 규정합니다.

2. 기본 구조 & 우선순위 #

2.1 settings.json 위치

권한 설정 파일 위치
범위파일 위치적용 대상
전역 ~/.gemini/settings.json 이 컴퓨터의 모든 워크스페이스
워크스페이스 프로젝트_루트/.gemini/settings.json 해당 프로젝트만 (팀 공유 가능)

두 파일이 동시에 존재하면 워크스페이스 설정이 전역을 재정의합니다. 단, 권한은 "겹치는 항목 중 더 엄격한 쪽"이 적용된다고 이해하면 안전합니다 (자세한 우선순위는 2.3 참조).

2.2 가장 단순한 형태

settings.json — permissions 블록
{
  "permissions": {
    "allow": [
      "Read(**/*.md)",
      "Edit(**/*.py)",
      "Write(**/*.json)",
      "Bash(git diff:*)"
    ],
    "deny": [
      "Read(**/.env)",
      "Edit(**/secrets/**)"
    ]
  }
}

각 항목은 도구이름(패턴) 형식의 단일 문자열입니다. 위 예시를 한 줄씩 풀어 읽으면 다음과 같습니다.

예시 패턴 해석
패턴의미
Read(**/*.md)워크스페이스 어디든 모든 .md 파일 읽기 자동 허용
Edit(**/*.py)모든 Python 파일 수정 자동 허용 (신규 생성은 별도)
Write(**/*.json)JSON 파일 신규 생성 또는 덮어쓰기 자동 허용
Bash(git diff:*)git diff로 시작하는 모든 셸 명령 자동 허용 (git diff, git diff HEAD 등)
Read(**/.env)이름이 .env인 모든 파일 읽기 영구 차단 (사용자 승인으로도 우회 불가)
Edit(**/secrets/**)secrets/ 디렉터리 안 모든 파일 수정 영구 차단

2.3 매칭 우선순위 (deny > allow > ask)

한 작업에 여러 패턴이 매칭될 수 있습니다. 이때 적용 순서는 다음과 같습니다.

  1. deny에 매칭되면 즉시 차단 — 사용자가 승인 버튼을 눌러도 실행되지 않습니다. 가장 강한 규칙입니다.
  2. allow에 매칭되면 자동 실행 — 별도의 사용자 확인 없이 진행됩니다.
  3. 둘 다 매칭되지 않으면 매번 사용자에게 묻기 — 기본 정책(ask)이 적용됩니다.
⚠️ 중요한 함정: "Read(**/*)"로 모든 읽기를 허용해도, "Read(**/.env)"가 deny에 있으면 .env는 절대 읽히지 않습니다. 보안에 민감한 패턴은 항상 deny에 명시하세요. allow가 deny를 덮어쓸 수 없습니다.

2.4 전역 vs 워크스페이스 병합 규칙

두 파일이 동시에 있으면 두 배열이 합집합으로 합쳐진 뒤 위 우선순위가 적용됩니다.

  • allow 합집합 — 전역과 워크스페이스 어느 한쪽에라도 있으면 허용
  • deny 합집합 — 어느 한쪽에라도 있으면 차단
  • 충돌 시 deny 승리 — 한쪽이 allow, 다른 쪽이 deny면 deny 적용
실전 패턴: 전역에는 "위험한 것은 무조건 deny"(**/.env, **/secrets/**, ~/.ssh/** 등)만 적고, allow는 워크스페이스별로 프로젝트 특성에 맞게 작성하면 안전성과 유연성을 동시에 잡을 수 있습니다.

3. Glob 패턴 문법 #

경로 패턴은 표준 Glob 문법을 따릅니다. 정규식이 아니라 셸의 와일드카드와 같습니다.

3.1 핵심 와일드카드

Glob 와일드카드 종류
기호의미매칭 예시매칭 안 됨
* 한 디렉터리 안의 임의의 문자 (구분자 / 제외) *.pymain.py, utils.py src/main.py (/ 포함)
** 모든 하위 디렉터리 재귀 매칭 **/*.pya.py, src/main.py, tests/unit/x.py
? 임의의 한 글자 file?.txtfile1.txt, fileA.txt file12.txt
[abc] 대괄호 안 글자 중 하나 v[12].mdv1.md, v2.md v3.md
{a,b} 중괄호 안 옵션 중 하나 (Brace Expansion) **/*.{js,ts}app.js, app.ts app.py

3.2 자주 헷갈리는 차이 — * vs **

한 줄 정리
* 한 개는 "이 디렉터리 안 한 단계"만, ** 두 개는 "여기부터 모든 하위 디렉터리"를 의미합니다.
패턴별 매칭 차이
# src 바로 아래 .py 파일만 (1단계)
"Edit(src/*.py)"
✅ src/main.py
❌ src/utils/helper.py    # 한 단계 더 깊음

# src 아래 모든 단계의 .py 파일
"Edit(src/**/*.py)"
✅ src/main.py
✅ src/utils/helper.py
✅ src/a/b/c/x.py

# 워크스페이스 어디든 .py 파일
"Edit(**/*.py)"
✅ main.py
✅ src/utils/helper.py
✅ tests/unit/test_x.py

3.3 자주 쓰는 패턴 사전

자주 쓰는 Glob 패턴
목적패턴
모든 마크다운 문서**/*.md
여러 확장자 동시 매칭**/*.{py,pyi,ipynb}
특정 디렉터리 전체tests/**
특정 디렉터리 제외 (deny와 조합)allow: **/*.py + deny: migrations/**/*.py
숨김 파일·디렉터리**/.* (모든 dotfile)
특정 환경설정 파일들**/{.env,.env.*,*.pem,id_rsa*}
홈 디렉터리 보호~/.ssh/**, ~/.aws/**, ~/.gnupg/**
운영 데이터 보호data/raw/**, data/prod/**
주의: ~/는 사용자 홈 디렉터리로 확장됩니다. 워크스페이스 밖의 절대 경로를 보호하고 싶을 때 유용합니다.

4. 도구별 패턴 형식 #

괄호 안에 들어가는 패턴 형식은 도구마다 조금씩 다릅니다.

4.1 파일 도구 — Read / Edit / Write

괄호 안에 파일 경로 Glob만 넣습니다.

파일 도구 권한 예시
# 읽기 — 파일 내용을 컨텍스트에 가져옴
"Read(**/*.md)"
"Read(docs/**)"
"Read(README.md)"

# 수정 — 기존 파일 변경
"Edit(src/**/*.py)"
"Edit(*.json)"

# 신규 생성 또는 덮어쓰기
"Write(output/**/*.csv)"
"Write(reports/*.html)"
Edit vs Write 구분: 기존 파일을 부분 수정하는 것은 Edit, 새 파일을 만들거나 통째로 덮어쓰는 것은 Write입니다. 두 권한은 독립적이므로 분석 결과만 새로 만들고 기존 코드는 못 고치게 하려면 Write만 허용하세요.

4.2 셸 도구 — Bash

Bash는 명령어 + : + 인자 패턴 형식을 씁니다. :*는 "이 명령어로 시작하는 모든 인자 조합"이라는 의미입니다.

Bash 권한 예시
# 정확히 'ls'만 허용 (인자 없음)
"Bash(ls)"

# 'git status'로 시작하는 모든 명령
"Bash(git status:*)"
✅ git status
✅ git status --short
✅ git status -uall

# 자주 쓰는 안전 명령 묶음
"Bash(git diff:*)"
"Bash(git log:*)"
"Bash(npm test:*)"
"Bash(pytest:*)"

# 위험 패턴은 deny로 차단
"Bash(rm -rf:*)"          # deny에 추가
"Bash(git push --force:*)"
"Bash(curl:* | bash:*)"
⚠️ 셸 권한의 함정: "Bash(git:*)"처럼 너무 넓게 허용하면 git push --force origin main도 자동 실행됩니다. 명령어는 동사 단위(git diff, git log, git status)로 분리해 허용하는 것이 안전합니다.

4.3 네트워크 도구 — WebFetch

괄호 안에 URL 패턴 또는 도메인을 넣습니다.

WebFetch 권한 예시
# 특정 도메인만 허용 (서브도메인 포함)
"WebFetch(domain:docs.python.org)"
"WebFetch(domain:github.com)"
"WebFetch(domain:stackoverflow.com)"

# 서브도메인 와일드카드
"WebFetch(domain:*.anthropic.com)"

# 사내망·민감 URL은 명시적 차단
"WebFetch(domain:*.internal.example.com)"   # deny에 추가

4.4 도구 형식 한눈에 보기

도구별 권한 패턴 형식
도구패턴 형식예시
Read파일 GlobRead(**/*.md)
Edit파일 GlobEdit(src/**/*.py)
Write파일 GlobWrite(output/*.csv)
Bash명령어:인자패턴Bash(git diff:*)
WebFetchdomain:호스트WebFetch(domain:github.com)

5. 실전 프리셋 — 복사해 시작하기 #

아래 프리셋을 출발점으로 삼아 프로젝트에 맞게 조정하세요. 모두 "deny는 보수적으로 / allow는 점진적으로"라는 원칙을 따릅니다.

5.1 데이터 분석 프로젝트 (Python + 노트북)

.gemini/settings.json (워크스페이스)
{
  "permissions": {
    "allow": [
      "Read(**/*.{md,py,ipynb,csv,xlsx,json,yaml,toml})",
      "Edit(**/*.{py,ipynb,md})",
      "Write(reports/**/*.{html,png,csv})",
      "Write(notebooks/**/*.ipynb)",
      "Bash(uv:*)",
      "Bash(python:*)",
      "Bash(pytest:*)",
      "Bash(jupyter:*)",
      "Bash(git status:*)",
      "Bash(git diff:*)",
      "Bash(git log:*)",
      "WebFetch(domain:docs.python.org)",
      "WebFetch(domain:pandas.pydata.org)",
      "WebFetch(domain:scikit-learn.org)"
    ],
    "deny": [
      "Read(**/.env)",
      "Read(**/.env.*)",
      "Read(**/secrets/**)",
      "Read(**/credentials.*)",
      "Edit(data/raw/**)",
      "Edit(data/prod/**)",
      "Bash(rm -rf:*)",
      "Bash(git push --force:*)",
      "Bash(git reset --hard:*)"
    ]
  }
}

의도: 노트북·스크립트·리포트는 자유롭게 작성·수정하되, 원본 데이터(data/raw, data/prod)와 비밀 파일은 절대 건드리지 못하게 합니다. 위험한 git 명령은 자동 실행을 막습니다.

5.2 웹 프론트엔드 프로젝트 (TypeScript + React)

.gemini/settings.json (워크스페이스)
{
  "permissions": {
    "allow": [
      "Read(**/*.{ts,tsx,js,jsx,json,md,css,scss,html})",
      "Edit(src/**/*.{ts,tsx,css,scss})",
      "Write(src/**/*.{ts,tsx})",
      "Edit(*.json)",
      "Bash(npm:*)",
      "Bash(pnpm:*)",
      "Bash(npx:*)",
      "Bash(tsc:*)",
      "Bash(vitest:*)",
      "Bash(eslint:*)",
      "Bash(prettier:*)",
      "WebFetch(domain:react.dev)",
      "WebFetch(domain:developer.mozilla.org)",
      "WebFetch(domain:typescriptlang.org)"
    ],
    "deny": [
      "Read(**/.env*)",
      "Edit(node_modules/**)",
      "Edit(dist/**)",
      "Edit(build/**)",
      "Bash(npm publish:*)",
      "Bash(rm -rf:*)"
    ]
  }
}

의도: src/ 안의 코드만 수정 가능하고, 빌드 산출물(dist, build, node_modules)은 보호됩니다. npm publish처럼 외부에 영향 가는 명령은 매번 확인이 필요하도록 deny.

5.3 전역 안전망 (모든 프로젝트 공통 deny)

~/.gemini/settings.json (전역)
{
  "permissions": {
    "deny": [
      "Read(**/.env)",
      "Read(**/.env.*)",
      "Read(**/secrets/**)",
      "Read(**/credentials.*)",
      "Read(~/.ssh/**)",
      "Read(~/.aws/**)",
      "Read(~/.gnupg/**)",
      "Read(**/id_rsa*)",
      "Read(**/*.pem)",
      "Edit(~/.ssh/**)",
      "Edit(~/.aws/**)",
      "Bash(rm -rf:*)",
      "Bash(rm -rf /:*)",
      "Bash(sudo:*)",
      "Bash(curl:* | bash:*)",
      "Bash(curl:* | sh:*)"
    ]
  }
}

의도: 워크스페이스 설정 실수와 무관하게 비밀·시스템 디렉터리·파괴적 명령은 항상 차단됩니다. allow는 비워두고 워크스페이스에서 프로젝트별로 작성하세요.

점진적 도입 팁: 처음에는 전역 deny + 워크스페이스 빈 allow로 시작하세요. 매번 확인 프롬프트가 뜨는 작업이 반복되면 그때마다 워크스페이스 allow에 추가합니다. 처음부터 광범위한 allow를 쓰면 어떤 작업이 자동 실행됐는지 추적이 어렵습니다.

6. 디버깅 & 트러블슈팅 #

6.1 권한이 적용되지 않을 때 체크리스트

  1. JSON 문법 오류 — 콤마 누락, 따옴표 불일치가 가장 흔합니다. cat .gemini/settings.json | python3 -m json.tool로 검증하세요.
  2. 재시작 누락 — 권한 변경은 Antigravity 재시작 후 적용됩니다. 변경 직후 같은 세션에서는 옛 정책이 동작합니다.
  3. 경로 패턴 미스매치*.py는 한 단계만, **/*.py는 모든 단계입니다. 6.3의 빠른 테스트로 확인하세요.
  4. 전역과 충돌 — 워크스페이스에서 allow한 항목이 전역 deny에 매칭되면 차단됩니다. 두 파일을 모두 확인하세요.
  5. 도구 이름 오타read가 아니라 Read입니다 (대소문자 구분).

6.2 "왜 자꾸 물어보지?" — 누락된 allow 찾기

같은 작업에 매번 확인 프롬프트가 뜨면, 사용자에게 표시된 도구·인자를 그대로 allow에 추가하세요. 예를 들어 "Bash uv pip install pandas 실행할까요?"가 반복된다면:

추가할 패턴
# 너무 좁음 — pandas 외에는 또 물어봄
"Bash(uv pip install pandas)"

# 적절 — 모든 패키지 설치 허용
"Bash(uv pip install:*)"

# 너무 넓음 — uv pip uninstall도 자동 실행됨
"Bash(uv:*)"

6.3 패턴 매칭 빠른 테스트

의심스러운 패턴은 셸의 Glob 확장으로 미리 확인할 수 있습니다.

bash/zsh — Glob 확인
# src/**/*.py 패턴이 어떤 파일을 매칭하는지 확인
shopt -s globstar    # bash에서 **를 활성화
ls src/**/*.py

# Python의 pathlib로 동일 검증 (OS 독립)
python3 -c "from pathlib import Path; print('\n'.join(str(p) for p in Path('.').glob('src/**/*.py')))"

6.4 자주 묻는 질문

Q. allow에 빈 배열이면 어떻게 되나요?
모든 도구 호출에 매번 사용자 확인을 요청합니다. 차단(deny)이 아니라 "매번 묻기"입니다. 완전 차단은 명시적으로 deny에 추가해야 합니다.
Q. allow와 deny에 같은 패턴이 있으면?
deny가 항상 승리합니다. 의도적으로 "예외적으로 한 파일만 허용"하려면, deny 패턴을 더 좁게 작성하세요. 예: deny **/secrets/** + allow secrets/sample.json → 후자도 deny에 매칭되어 차단됨. 대신 deny를 secrets/**/*.real.json처럼 좁히세요.
Q. MCP 서버의 도구도 권한으로 제어되나요?
네. MCP 서버 도구는 mcp__<server>__<tool> 형식의 도구 이름으로 매칭합니다. 예: "mcp__github__create_pull_request(*)". 자세한 형식은 도구 호출 시 표시되는 이름을 참고하세요.

오늘코드 Antigravity 튜토리얼 — Google Antigravity 공식 문서 기반 한국어 학습 가이드

이 튜토리얼은 비공식 학습 자료입니다. 공식 문서: antigravity.google/docs

오늘코드