본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 16. 10:52

Claude Code 안전성: Hooks, Sandboxes, 그리고 불안감 없이 자율적으로 실행하기

요약

Claude Code의 자율 실행 시 발생할 수 있는 위험을 방지하기 위한 네 가지 보안 가드레일 전략을 소개합니다. 커스텀 훅, 내장 샌드박스, Docker microVM 등을 활용하여 안전하게 Bash 명령어를 실행하는 방법을 다룹니다.

핵심 포인트

  • PreToolUse 훅을 통한 프로그래밍 방식의 명령어 제어
  • 내장된 /sandbox 기능을 이용한 파일 및 네트워크 격리
  • Docker microVM을 활용한 가장 강력한 수준의 격리 환경 구축
  • 자율 실행 모드에서의 보안 공백을 메우는 계층적 방어 전략

요약 (TL;DR): Claude Code는 Bash를 실행하며, 이는 위험한 Bash 명령을 실행할 수도 있음을 의미합니다. 이를 방어하기 위한 가드레일(guardrails)을 설정하는 방법은 많습니다. 잘 알려진 네 가지 방법은 다음과 같습니다: 직접 PreToolUse hooks 작성하기 (가볍고, 이식성이 높으며, 사용자 정의 가능), 내장된 /sandbox 사용하기 (파일 시스템 및 네트워크 격리), Docker microVM 내부에서 실행하기 (가장 강력한 격리), 또는 커뮤니티의 hook 모음 사용하기. 이 글에서는 이 네 가지 방법을 살펴보고, 어떤 플러그인에도 바로 복사해서 붙여넣을 수 있는 hook 예제로 마무리합니다.

Claude가 빌드 디렉토리를 정리하던 중, 제 홈 폴더로 연결되는 경로를 포함한 rm -rf 명령어를 생성했습니다. 와일드카드(glob)가 잘못 확장된 것이었습니다. 명령어 자체는 문법적으로 문제가 없었으며 곧 실행될 상황이었습니다.

하지만 실행되지 않았습니다. 하나의 hook이 이를 포착하여 종료 코드(exit code) 2를 반환했기 때문입니다. Claude는 거부된 것을 확인하고, 범위가 제한된(scoped) 경로로 다시 시도했습니다.

안전 도구(Safety tooling)의 가치는, 아무런 문제가 없는 수백 개의 명령어는 방해하지 않으면서, 당신의 하루를 망칠 수 있는 소수의 명령어들을 잡아냄으로써 그 존재 가치를 증명합니다. 이를 위한 방법은 많습니다. "10줄의 Bash"부터 "전체 microVM"까지, 네 가지 잘 알려진 방법과 각각이 언제 유용한지 소개합니다.

이 글의 URL을 Claude Code에 직접 전달하여 따라 해 보실 수 있습니다.

권한 모델: Claude Code가 무엇을 실행할지 결정하는 방식

가드레일을 살펴보기 전에, 가드레일이 작동하는 대상에 대해 알아봅시다.

Claude가 도구를 사용하려고 할 때마다, Claude Code는 이를 권한 확인(permission check) 절차를 거치게 합니다. Bash 명령어는 사용자의 허용(allow) 및 거부(deny) 규칙과 대조됩니다. 일반 모드에서는 위험한 명령어를 하나씩 수동으로 승인해야 합니다.

실제 세션을 실행해 본 사람이라면 이 상황이 어떻게 흘러가는지 잘 알 것입니다. 명령어가 나올 때마다 승인, 승인, 승인... 계속되는 승인 과정에 지쳐 결국 업무를 마치기 위해 바이패스(bypass) 모드를 켜버리게 됩니다. 바로 여기에 공백이 생깁니다. Claude를 자율적으로 실행하도록 허용하는 순간, 수동 승인 단계가 사라지며, 인간의 개입(human in the loop) 없이 잘못된 명령어가 실행될 수 있습니다.

그러한 트레이드오프(tradeoff)가 바로 더 자동화된 접근 방식들이 존재하는 정확한 이유입니다. 모든 것을 승인하거나 혹은 아무것도 승인하지 않는 대신, 이 방식들은 Claude가 자유롭게 실행되도록 허용하되 실제로 중요한 경우에만 실행을 중단합니다. 훅(Hooks)은 명령어를 가로채어 프로그래밍 방식으로 결정합니다. 샌드박스(Sandboxes)는 어떤 명령어도 건드릴 수 있는 범위를 제한합니다. 이들은 계층적으로 쌓이기 때문에, 하나만 선택할 필요가 없습니다.

접근 방식 A: 커스텀 훅(Custom hooks) - 사용자가 소유하는 가볍고 휴대 가능한 옵션

훅(hook)은 Claude Code가 자신의 라이프사이클(lifecycle) 중 특정 시점에 실행하는 스크립트입니다. 안전을 위해 필요한 것은 PreToolUse입니다. 이는 도구가 실행되기 전에 트리거되며, 종료 코드(exit code)가 다음 동작을 결정합니다.

세 가지 결과:

  • 종료 코드 0 - 명령어를 허용합니다. 선택적으로 systemMessage가 포함된 JSON을 출력하여 차단하지 않고 경고를 줄 수 있습니다.
  • 종료 코드 2 - 명령어를 차단합니다. stderr에 작성하는 모든 내용은 Claude에게 보여지므로, Claude는 이유를 이해하고 조정할 수 있습니다.
  • JSON 결정 - 바이패스(bypass) 모드에서도 커스텀 사유와 함께 거부할 수 있도록 permissionDecision 객체를 출력합니다.

플러그인 내부의 hooks.json 파일에서 이를 연결합니다:

{
  "hooks": {
    "PreToolUse": [
...

matcherBash이므로, 이는 Bash 명령어에 대해서만 실행됩니다. ${CLAUDE_PLUGIN_ROOT}는 플러그인의 디렉토리로 해석되므로, 어떤 머신에서도 경로가 작동합니다.

스크립트는 stdin으로부터 명령어를 JSON으로 읽어 들여 추출하고, 패턴과 대조하여 확인합니다. 기본 구조는 단순히 읽기, 페일 오픈(fail-open) 가드, 그리고 하나의 차단 규칙으로 구성됩니다:

#!/bin/bash
set -euo pipefail

...

비밀 정보 탐지(secret detection), 강제 푸시(force-push) 게이트 및 경고가 포함된 전체 스크립트는 이 글의 마지막에 있습니다.

언급할 만한 두 가지 설계 선택 사항이 있습니다.

페일 오픈(Fail open). 만약 스크립트가 명령어를 파싱할 수 없다면, 0으로 종료하고 통과시킵니다. 정규 표현식(regex)이 예외 상황(edge case)을 만날 때마다 모든 Bash 호출을 망가뜨리는 안전 훅은 훅이 없는 것보다 더 나쁩니다. 왜냐하면 하루도 안 되어 제거하게 될 것이기 때문입니다. 따라서 명백히 위험한 것들만 차단하고 나머지는 통과시키십시오.

항상 파괴적인 것은 차단하고, 가끔 잘못될 수 있는 것은 경고하십시오. rm -rf ~는 결코 의도한 결과가 아닐 것이므로 차단하십시오. git reset --hard는 때때로 정확히 필요한 작업일 수 있으므로, 경고를 띄우고 Claude가 컨텍스트에 표시된 경고를 확인한 후 직접 결정하게 하십시오.

진정한 가드 스크립트(guard script)는 시간이 흐르며 더 많은 패턴을 갖추게 됩니다. 흔히 추가되는 항목들은 다음과 같습니다:

  • 셸(shell)을 통한 .env 쓰기 차단 (echo ... > .env)
  • --force-with-lease가 아닌 경우 git push --force 차단
  • git clean -f, DROP TABLE, TRUNCATE, 운영 환경(production) 키워드에 대해 경고
  • 명시적인 확인 토큰(confirmation token)을 통해 git push를 제어

이 모든 구성 요소는 이식성이 높습니다. 데몬(daemon)이나 설치할 것이 없는 셸 스크립트와 JSON 파일로 이루어져 있습니다. 이는 사용자의 플러그인과 함께 작동하며 Linux, macOS, WSL 및 Windows의 Git Bash에서 동작합니다. 물론 트레이드오프(tradeoff)는 있습니다. 미리 작성해 둔 패턴만 잡아낼 수 있다는 점입니다. 즉, 모든 필터가 가진 허점을 가진 스마트한 필터인 셈입니다.

강제 푸시(force-push) 제어와 전체 패턴 목록이 포함된 이 스크립트의 더 완전한 버전은 참조 리포지토리(reference repo)에 있습니다: github.com/Nagell/claude-marketplace.

접근 방식 B: 네이티브 샌드박스(Native sandbox) - 내장된 파일 시스템 및 네트워크 격리

Claude Code는 /sandbox 명령어로 활성화할 수 있는 샌드박스(sandbox)를 제공합니다. 명령어를 검사하는 대신, 어떤 명령어가 수행할 수 있는 동작을 제한합니다.

두 가지 계층의 격리:

  • 파일 시스템 (Filesystem) - 기본적으로 쓰기 작업은 현재 작업 디렉토리(current working directory)로 잠깁니다. 명령어는 광범위하게 읽을 수 있지만, 사용자가 허용하지 않는 한 프로젝트 외부에는 쓸 수 없습니다. 이는 allowWritedenyWrite 규칙으로 조정할 수 있습니다.
  • 네트워크 (Network) - 외부 트래픽은 허용 목록(allowlist)이 있는 로컬 프록시(local proxy)를 통해 전달됩니다. 승인된 도메인은 통과하지만, 그 외의 모든 것은 차단됩니다. 임의의 호스트로 예기치 않은 호출이 발생하는 것을 방지합니다.

그 결과로 중단(interruption)이 줄어듭니다. 샌드박스(sandboxed) 명령은 박스를 벗어날 수 없기 때문에, Claude Code는 명령을 하나씩 승인해 달라고 사용자에게 요청하는 것을 멈춥니다. 실제로 이는 자율 세션(autonomous session) 동안 권한 요청(permission prompts)을 크게 줄여주며, 이것이 바로 자율 세션을 실행하는 근본적인 이유입니다.

플랫폼 지원이 제약 사항입니다:

  • macOS - OS Seatbelt 샌드박스를 사용하며, 즉시 작동합니다.
  • Linux / WSL2 - bubblewrap을 사용하며, 직접 설치해야 합니다 (또한 socat이 필요하며, Ubuntu 24.04+ 버전은 AppArmor 수정이 필요합니다).
  • WSL1 - 지원되지 않습니다.

기타 주의 사항: Docker와 watchman은 샌드박스 내부에서 잘 작동하지 않으며, 탈출구(escape hatch)가 존재합니다. 샌드박스 제한으로 인해 명령이 실패할 경우, Claude는 dangerouslyDisableSandbox를 사용하여 재시도할 수 있습니다. 이 재시도는 샌드박스 외부에서 실행되지만 일반적인 권한 흐름(permission flow)을 다시 거치므로, 여전히 사용자에게 승인을 요청합니다. 이는 조용히 우회하는 것이 아닙니다. 탈출구를 완전히 제거하려면 allowUnsandboxedCommands: false로 설정하면 되며 (/sandbox 패널의 Strict sandbox mode), 이 경우 해당 파라미터는 무시됩니다.

출처: code.claude.com/docs/en/sandboxing

접근 방식 C: Docker microVM - 가장 강력한 격리, 팀 친화적

Hooks와 네이티브 샌드박스만으로 충분하지 않을 때는 한 단계 더 높여서, Claude를 Docker microVM 내부에서 실행합니다.

이것은 호스트 커널(host kernel)을 공유하는 컨테이너가 아닙니다. 각 샌드박스는 자체 커널과 프라이빗 Docker 데몬(private Docker daemon)을 가진 완전한 microVM을 할당받습니다. 사용자의 개발 환경이 복제되어 들어오고, Claude는 그 안에서 작동하며, Claude가 수행하는 그 어떤 것도 호스트에 영향을 주지 않습니다. 최악의 경우, 해당 VM을 그냥 버리면 됩니다.

이 방식은 다음 두 가지 상황에서 올바른 선택입니다:

  • 팀(Teams) - 모든 구성원이 동일한 격리된 환경을 갖게 되며, 한 명의 실수는 해당 인원에게만 국한됩니다.
  • 장시간 실행되는 자율 에이전트(Long-running autonomous agents) - Claude가 관리자 없이 몇 시간 동안 실행되어야 한다면, 단일 명령의 영향 범위(blast radius)는 사용자의 노트북이 아니라 폐기 가능한 VM이어야 합니다.

그 대가는 설정과 오버헤드(overhead)입니다. VM(가상 머신)을 실행하는 것은 훅(hook)이나 네이티브 샌드박스(native sandbox)보다 더 무겁습니다. 짧은 세션에는 과할 수 있습니다. 하지만 에이전트(agent)를 밤새도록 방치한 채 실행해 두어야 한다면, 이 네 가지 방식 중 실제로 당신이 잠을 잘 수 있게 해주는 유일한 방법입니다.

공식 가이드: Docker Sandboxes for Claude Code

접근 방식 D: 커뮤니티 컬렉션 - 거인의 어깨 위에 올라타기

모든 패턴을 직접 작성할 필요는 없습니다. 이미 관리되고 있는 여러 훅(hook) 컬렉션이 존재하며, 이들은 당신이 아직 발견하지 못한 예외 상황(edge cases)들을 이미 겪어냈습니다:

  • karanb192/claude-code-hooks - 전형적인 위협들을 차단합니다: rm -rf ~, 포크 폭탄(fork bombs), curl | sh 등.
  • CodyLunders/claude-code-hooks-library - 55개의 훅이 포함되어 있으며, 그중 12개는 AWS 자격 증명 스캐닝(AKIA[0-9A-Z]{16})과 대화형 설치 프로그램을 포함한 보안 특화 훅입니다.
  • disler/claude-code-hooks-mastery - 교육용으로, 여러 보안 패턴을 단계별로 안내하여 단순히 설정(config)뿐만 아니라 그 메커니즘을 배울 수 있게 합니다.
  • Boucle - Claude Code를 위한 독립형 안전 훅 프레임워크입니다: framework.boucle.sh.

또한 108시간의 자율 운영(autonomous operation)을 통해 추출한 10개의 훅에 대한 DEV Community 기술 문서도 있습니다. 이는 당신이 직접 무언가를 만들기 전에 읽어볼 가치가 있는, 바로 그 실전 검증된(battle-tested) 목록입니다.

따라서 이 중 하나를 훑어보고, 당신의 환경에 맞는 패턴을 가져와서 당신만의 가드 스크립트(guard script)에 적용하세요. 파일을 직접 소유함으로써 이식성(portability)을 유지할 수 있고, 누군가가 이미 대가를 치르며 배운 교훈을 다시 배울 필요도 없습니다.

비교

커스텀 훅 (Custom hooks)네이티브 샌드박스 (Native sandbox)Docker microVM커뮤니티 훅 (Community hooks)
격리 수준 (Isolation level)패턴 기반 필터 (Pattern-based filter)파일 시스템 + 네트워크 (Filesystem + network)전체 VM, 자체 커널 (Full VM, own kernel)패턴 기반 필터 (Pattern-based filter)
...

중요한 차이점은 마지막 행에 있습니다. 훅 (hook)은 이미 패턴을 작성해 둔 것만 잡아내지만, 샌드박스 (sandbox)는 애초에 어떤 명령어가 무엇을 건드릴 수 있는지 자체를 제한하므로, 예상치 못한 상황까지도 차단합니다. 이것이 강력한 설정들이 이들을 중첩하여 사용하는 이유입니다. 한눈에 읽을 수 있는 빠르고 프로젝트 특화된 규칙을 위해 상단에 훅 (hook)을 두고, 그 아래에 나머지 모든 것을 위한 최후의 보루로서 샌드박스 (sandbox)를 배치합니다.

실제로 무엇을 사용해야 하는가

  • 대부분의 개발자, 대부분의 경우: 커스텀 훅 (custom hooks). 가볍고 이식성(portable)이 있으며, 무엇을 하는지 정확히 이해할 수 있습니다. 여기서부터 시작하세요.
  • 빈번한 자율 세션 (Frequent autonomous sessions): 상단에 네이티브 샌드박스 (native sandbox)를 추가하세요. 중단(interruption)을 줄이는 것만으로도 Linux 설정 비용을 충분히 뽑아냅니다.
  • 팀 단위 또는 야간 에이전트 (overnight agents): Docker microVM. 폭발 반경(blast radius)이 반드시 제로여야 한다면, 다른 어떤 것도 이를 달성할 수 없습니다.

훅 (hook)부터 시작하세요. 다음은 플러그인의 hooks/ 디렉토리에 복사하여 앞서 보여준 hooks.json을 통해 연결할 수 있는 예시입니다:

#!/bin/bash
# safety-guards.sh - Bash를 위한 PreToolUse 훅
# Exit 0 = 허용, exit 2 = 차단 (stderr가 Claude에게 표시됨)
...

이를 플러그인에 포함하여 배포하면 Claude Code가 모든 Bash 호출 전에 이를 실행합니다. (파일에는 실행 권한(executable bit)이 필요하며, 이는 한 번 설정하여 커밋하면 됩니다. git이 이를 보존하므로, 설치 후 아무도 chmod를 실행할 필요가 없습니다.) 문제가 되는 패턴을 발견할 때마다 패턴을 추가하세요.

Claude에게 이러한 규칙을 직접 작성하게 할 수도 있습니다. 만약 그렇게 한다면, 테스트도 함께 요청하세요. 각 패턴을 트리거해야 하는 가짜 명령들(가짜 rm -rf ~, 심어놓은 비밀 정보, git push --force 등)을 훅 (hook)에 입력하게 하여 실제로 차단되는지 확인하도록 하세요. 또한, 실제 명령어가 빠져나가지 않도록 정규 표현식(regex)이 너무 느슨하지 않은지도 확인해달라고 요청하세요. 이는 패턴이 너무 탐욕스럽거나(greedy) 너무 좁아서 정작 본인이 당하기 전에, 잘못된 패턴을 잡아내는 가장 빠른 방법입니다.

그것은 당신이 소유하며, 한 번에 읽어 내려갈 수 있는 파일 안에 담긴 안전망입니다.

시작하기

모든 것이 미리 연결된 깨끗한 상태로 시작하려면 스타터 템플릿(starter template)을 사용하세요: github.com/Nagell/claude-marketplace-template.

이 템플릿은 하나의 빈 플러그인(plugin), 합리적인 기본값이 설정된 CLAUDE.md, 그리고 버전 관리(versioning)와 릴리스(releases)를 자동으로 처리하는 GitHub Actions 워크플로(workflow)를 제공합니다. GitHub에서 "Use this template"을 클릭하면 첫 번째 플러그인을 추가할 준비가 완료됩니다.

여러 개의 플러그인과 실제 훅 스크립트(hook scripts)가 포함된 더 완전한 작동 예시를 보고 싶다면, 이 시리즈 전반에서 참조 리포지토리(reference repo)로 사용되는 github.com/Nagell/claude-marketplace를 확인하세요.

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0