Vol.1-3 리캡:
지금까지 뭘 제어했나
| Vol. | 제어한 것 | 메커니즘 | 핵심 질문 |
|---|---|---|---|
| Vol.1 | 행동 차단 | Hook exit code | 뭘 할 수 있는지? |
| Vol.2 | 역할 분리 | tools 필드 | 누가 하는지? |
| Vol.3 | 평가 객관화 | Evaluator + rubric | 얼마나 잘 했는지? |
| Vol.4 | 도구 경계 + 보안 | 5개 제어축 | 어디까지 닿을 수 있는지? |
tools: Read, Write로 내장 도구를 제한했어요. 하지만 에이전트가 Bash를 통해 서버에 SSH하거나, MCP로 데이터베이스에 접근하거나, 다른 에이전트를 스폰해서 배포하는 것까지는 제어하지 못했거든요. Vol.4에서는 에이전트가 외부 세계와 접촉하는 모든 경로의 경계를 설계합니다 — 그리고 이건 자연스럽게 에이전트 보안이 돼요.
경계 없는 에이전트의
공격 표면
공격 표면(Attack Surface)이란 외부에서 시스템에 침투할 수 있는 모든 경로를 말해요. 에이전트에게 권한이 많을수록 공격 표면이 넓어지고, 실수든 악의적 공격이든 피해 범위가 커져요.
Bash 무제한
editor 에이전트가 문법 수정 중 git push --force를 실행해서 main 브랜치를 덮어씀
MCP 무제한
researcher 에이전트가 조사 중 Slack MCP로 "#general 채널"에 미완성 초안을 전송함
Agent 스폰 무제한
creator 에이전트가 자체적으로 deployer 에이전트를 스폰해서 프로덕션에 배포함
Permission 없음
fact-checker 에이전트가 검증 중 rm -rf /tmp/*로 임시 파일을 전부 삭제함
5개 축으로 보는
도구 제어 전체 지도
Claude Code에서 에이전트의 도구 접근을 제어하는 메커니즘은 정확히 5개예요. 각각 독립적으로 작동하고, 서로 겹치지 않아요. 보안 용어로는 이걸 심층 방어(Defense in Depth)라고 해요 — 여러 겹의 방어선을 쌓아서 하나가 뚫려도 다음 층이 막아주는 구조예요.
| 축 | 제어 대상 | 설정 위치 | 막는 보안 위협 |
|---|---|---|---|
| 1 | 내장 도구 | 에이전트 프론트매터 | 불필요한 파일 수정/삭제 |
| 2 | 에이전트 스폰 | 에이전트 프론트매터 | 권한 에스컬레이션 |
| 3 | MCP 서버 | 에이전트 프론트매터 | 데이터 유출, 악성 MCP |
| 4 | 승인 방식 | 에이전트 프론트매터 | 무분별한 자동 실행 |
| 5 | 글로벌 정책 | settings.json | 조직 전체 위험 명령 |
+ 보너스: PreToolUse Hook은 런타임 조건부 차단으로, Vol.1에서 이미 다뤘어요. 위 5개 정적 제어 + Hook 동적 제어를 조합하면 완성형 보안 하네스가 돼요.
tools / disallowedTools
내장 도구 제어
Vol.2에서 배운 tools 화이트리스트의 반대편 — disallowedTools 블랙리스트도 있어요. 쉽게 말하면 "이것만 쓸 수 있다" vs "이것만 못 쓴다"의 차이예요.
"이것만 쓸 수 있다"
명시한 도구만 허용하고, 나머지는 전부 차단해요. Vol.2에서 이미 사용한 방식이에요. 보안 관점에서는 이게 더 안전해요 — 허용한 것만 되니까요.
tools: Read, Grep, Glob, WebSearch, WebFetch # → Write, Edit, Bash, Agent 전부 사용 불가 # → 파일 수정도, 명령 실행도, 에이전트 스폰도 못 함
"이것만 못 쓴다"
명시한 도구만 차단하고, 나머지는 전부 허용해요. 대부분의 도구를 쓰되 위험한 것만 빼고 싶을 때 편해요. 다만 새로운 도구가 추가되면 자동으로 허용되니까, 화이트리스트보다 보안이 느슨해요.
disallowedTools: Write, Bash # → Read, Edit, Grep, Glob, WebSearch... 전부 사용 가능 # → 파일 생성과 명령 실행만 차단
에이전트 스폰과
MCP 서버 스코핑
누구를 부를 수 있는지(축 2), 어떤 외부 서비스에 닿을 수 있는지(축 3)를 제어해요. 보안 용어로는 수평 이동(Lateral Movement) 차단이에요 — 한 에이전트가 다른 에이전트나 서비스로 옮겨가면서 권한을 확장하는 걸 막는 거예요.
스폰할 수 있는 서브에이전트 제한
coordinator가 worker와 researcher만 부를 수 있고, deployer는 못 부르게 제한하는 거예요. 이러면 coordinator가 아무리 "배포해야 한다"고 판단해도 deployer를 스폰할 수 없어요.
tools: Agent(worker, researcher), Read, Bash # → deployer 에이전트는 스폰 불가 # → 프로덕션 배포 사고 원천 차단
에이전트별 MCP 서버 접근 제한
MCP(Model Context Protocol)는 에이전트가 외부 서비스(DB, 브라우저, Slack 등)에 접속하는 통로예요. 이 통로를 에이전트마다 다르게 열어줄 수 있어요.
mcpServers: - supabase # → 메인 세션의 supabase MCP만 재사용 가능 # → Slack, GitHub, 브라우저 등 다른 MCP는 접근 불가 # → DB는 읽되, 다른 곳에 데이터를 보낼 수 없음
mcpServers: - playwright: type: stdio command: npx args: ["-y", "@playwright/mcp@latest"] # → 이 에이전트에서만 Playwright MCP 연결 # → 에이전트 종료 시 자동 해제 (context 절약)
승인 프로세스와
글로벌 정책
도구를 허용하되 "어떻게 사용하는지"를 제어하는 축 4와, 프로젝트 전체에 거부 규칙을 강제하는 축 5예요.
도구 사용 승인 방식
같은 Bash 도구라도, 어떤 에이전트는 자동으로 실행하고, 어떤 에이전트는 매번 사용자에게 "이거 실행해도 돼요?" 하고 물어보게 만들 수 있어요.
| 모드 | 동작 | 보안 수준 |
|---|---|---|
plan | 읽기만 가능 (탐색 모드) | 가장 엄격 |
dontAsk | 미승인 도구 자동 거부 | 엄격 |
acceptEdits | 파일 편집만 자동 수락 | 중간 |
bypassPermissions | 모든 권한 프롬프트 생략 | 가장 느슨 |
프로젝트 전체 거부/허용 규칙
에이전트 개별 설정이 아니라, 프로젝트 레벨에서 "이건 누구도 못 한다"를 강제하는 거예요. 보안 용어로는 조직 정책(Organization Policy)이에요 — 개인이 아무리 바꾸려 해도 조직 규칙이 우선해요.
{
"permissions": {
"deny": [
"Bash(git push *)", // 원격 푸시 차단
"Bash(rm -rf *)", // 재귀 삭제 차단
"Bash(docker rm *)", // 컨테이너 삭제 차단
"Agent(deployer)" // deployer 스폰 차단
],
"allow": [
"Bash(git status)",
"Bash(git diff *)",
"Bash(git log *)",
"Bash(git add *)",
"Bash(git commit *)"
]
}
}평가 순서: deny → ask → allow. deny가 최우선이라, allow에 있어도 deny에 있으면 무조건 차단돼요.
직접 해보기:
settings.json으로 git push 차단
축 5(settings.json)를 직접 설정하고, 에이전트가 git push를 시도할 때 차단되는 걸 확인해봐요.
Step 1. 프로젝트 구조 만들기
├── .claude/
│ ├── settings.json ← 거부 규칙 설정
│ └── agents/
│ └── writer.md ← git push 시도하는 에이전트
└── (git init 필요)
Step 2. settings.json 작성
{
"permissions": {
"deny": ["Bash(git push *)", "Bash(rm -rf *)"],
"allow": [
"Bash(git status)", "Bash(git add *)",
"Bash(git commit *)", "Bash(echo *)"
]
}
}Step 3. writer 에이전트 작성
--- name: writer description: 파일을 작성하고 git에 커밋하는 에이전트 tools: Read, Write, Bash --- 요청받은 내용을 파일로 작성하고 git에 커밋한다. 커밋 후 git push origin master로 원격에 푸시한다.
Step 4. 실행 결과 (실제 테스트)
hello.md 작성 완료git add hello.md ✅git commit -m "Add hello.md" ✅
git push가 권한 설정에 의해 차단되었습니다.로컬 작업(파일 생성 + 커밋)은 모두 완료된 상태이니, 터미널에서 직접 실행해주세요:
git push origin master
settings.json의 deny: ["Bash(git push *)"] 규칙이 인프라 레벨에서 차단했어요. 프롬프트로 "푸시하지 마"라고 부탁한 게 아니라, 물리적으로 못 하게 막은 거예요.
git push --force를 실행시키려 해도, settings.json의 deny 규칙이 먼저 평가되기 때문에 실행 자체가 불가능해요. 에이전트의 "의지"와 무관하게 인프라가 차단하는 거예요.
하네스 아키텍처
전체 지도
| Vol. | 질문 | 메커니즘 | 보안 원칙 |
|---|---|---|---|
| 1 | 뭘 할 수 있는지? | Hook exit code | 런타임 검증 |
| 2 | 누가 하는지? | tools 필드 | 역할 기반 접근 제어 |
| 3 | 얼마나 잘 했는지? | Evaluator + rubric | 독립 감사 |
| 4 | 어디까지 닿는지? | 5개 제어축 | 최소 권한 + 심층 방어 |
최소 권한이 최강 보안이다
Vol.1~4를 관통하는 하나의 원칙이 있어요 — 에이전트에게 "필요한 만큼만" 허용하고, 나머지는 전부 차단하는 것.
이건 단순한 실수 방지가 아니라, 에이전트 시대의 보안 아키텍처예요. 프롬프트 인젝션이든, 악성 MCP 서버든, 권한 에스컬레이션이든 — 애초에 닿을 수 없으면 뚫릴 수도 없거든요.
프롬프트로 "조심해줘"라고 부탁하는 건 방화벽 없이 직원에게 "해커 조심해"라고 말하는 거랑 같아요. 인프라로 강제해야 보안이에요.
+ 역할 분리(tools)
+ 평가 객관화(Evaluator)
+ 도구 경계(5개 제어축)
= 에이전트 보안 하네스