Grith syscall 감시 프록시로 코딩 에이전트 접근 통제하기
코딩 에이전트한테 "이 버그 좀 고쳐줘"라고 던지고 자리를 비운 적, 다들 있으실 거예요. 그런데 그 사이 에이전트가 어떤 파일을 읽고 어디로 네트워크 요청을 보냈는지 전부 기억하시나요? Claude Code나 Cursor 같은 코딩 에이전트는 셸 명령 실행과 파일 쓰기, 외부 서버 접속 권한을 사실상 통째로 쥐고 자동화 작업을 돌립니다. 이 글을 따라오시면 Grith라는 syscall(시스템 콜) 감시 프록시를 설치해서, 에이전트의 어떤 행동을 자동 허용하고 어떤 행동을 승인 대기열로 보내고 어떤 행동을 아예 차단할지 직접 설정할 수 있게 됩니다. 지난주 로컬 개발 환경에 Grith를 붙여 Claude Code 세션 하나를 통째로 감싸봤는데, 그 결과를 기준으로 설치부터 튜닝까지 순서대로 정리했습니다.
준비물: 리눅스와 커널 버전부터 확인하자
Grith는 리눅스 전용으로 안정 지원됩니다. x86_64는 커널 4.8 이상, aarch64는 커널 5.3 이상이 필요하고 macOS·윈도우는 각각 Endpoint Security·ETW 백엔드가 필요한 v2.0에서나 지원될 예정입니다. 제 작업 머신은 우분투 계열이라 uname -r로 커널 버전부터 확인했습니다. 여기에 Claude Code 같은 코딩 에이전트 CLI가 하나 이상 깔려 있으면 됩니다. Codex·Aider·Cursor·Cline·Copilot·Goose를 포함해 열한 종의 내장 프로파일이 이미 준비돼 있어 대부분의 자동화 워크플로우에 바로 적용됩니다.
Grith는 정확히 무엇을 통제하나요?
Grith는 에이전트 프로세스가 발생시키는 모든 파일 읽기, 셸 명령, 네트워크 호출, 프로세스 스폰을 커널이 실행하기 직전에 가로채 점수를 매깁니다. 점수 3.0 미만이면 그대로 통과, 3.0에서 8.0 사이면 그 자리에서 멈춰 사람이 승인하거나 거부할 때까지 대기, 8.0을 넘으면 아예 실행되지 않습니다. 애매한 상태로 넘어가는 호출이 없다는 게 핵심입니다. 공개된 시연 사례를 보면 Claude Code가 평범한 파일 읽기·쓰기·테스트 실행은 통과시키다가, 환경변수 파일을 외부 호스트로 전송하려는 순간 커널 경계에서 막힙니다. 애플리케이션 레이어 필터와 다른 지점인데, 에이전트가 우회 코드를 스스로 짜내더라도 syscall 자체가 커널 밖으로 못 나가면 소용이 없습니다.
단계별로 설치하고 첫 에이전트를 감싸보자
1단계: 설치 스크립트 실행
터미널에 curl -fsSL https://grith.ai/install | sh를 입력하면 설치 스크립트가 현재 플랫폼을 자동 감지하고 체크섬을 검증한 뒤 ~/.local/bin에 바이너리를 놓습니다. 시스템 전체에서 쓰려면 --global 옵션으로 /usr/local/bin에 설치하고, 특정 버전에 고정하려면 --version 옵션을 씁니다. 이렇게 실행하면 → 몇 초 안에 grith 명령이 PATH에 잡히고 버전 확인이 정상 출력됩니다.
2단계: 기존 에이전트를 그대로 감싸기
기존 명령 앞에 grith exec --만 붙이면 됩니다. grith exec -- claude-code "fix the failing test"라고 입력하면 → Claude Code가 평소처럼 작동하는데, 뒤에서 모든 syscall이 실시간 채점되고 로컬 SQLite 감사 로그에 남습니다. Grith 자체 에이전트로 돌리고 싶으면 grith run "list every TODO in this repo"처럼 실행해도 같은 필터가 앞단에 걸립니다.
3단계: 프로파일로 대기열 소음 줄이기
기본 프로파일 열한 종이 각 도구의 일상 작업을 자동 허용해 두어 처음부터 승인 대기열이 폭주하지는 않습니다. 다만 사내 스크립트가 쓰는 커스텀 바이너리 하나는 기본 프로파일에 없어서 계속 대기열로 넘어갔는데, 프로파일 설정 파일에 그 바이너리를 허용 목록으로 추가하니 다음 실행부터 조용히 통과했습니다.
큐에 걸린 요청은 어떻게 처리하나요?
점수 3.0~8.0 구간에서 멈춘 프로세스는 사람이 승인하거나 거부하기 전까지 정지합니다. 대화형 세션은 터미널에서 바로 응답하면 되지만, CI처럼 사람이 없는 비대화형 세션은 물어볼 사람이 없으니 실패 안전 원칙에 따라 자동 거부됩니다. 버전 0.2.5부터는 다른 감시받지 않는 프로세스로 작업을 넘기는 행위, 예를 들어 도커나 tmux 스폰도 기본적으로 대기열로 보내집니다. CI 파이프라인에서 이런 위임이 실제로 필요하면 해당 바이너리를 프로파일에 명시적으로 허용하거나 관련 설정값을 꺼야 막힘 없이 돌아갑니다.
흔한 실수와 해결법
가장 크게 헤맨 건 감사 로그가 외부로 나가는 줄 알고 무료 버전을 꺼렸던 일입니다. 실제로는 무료 티어가 완전 오프라인으로 동작하고 계정도 텔레메트리도 없으며, 원본 감사 로그는 로컬 SQLite에만 남습니다. 유료 버전이라 해도 하루 한 번 라이선스 검증 통신만 나가고 명령어나 파일 경로가 아니라 집계된 판정 건수만 동기화됩니다. 두 번째는 소스 빌드였는데, Rust와 Node 버전을 맞추지 않고 빌드부터 돌리는 바람에 중간에 멈췄습니다. 배포된 바이너리를 그냥 받는 쪽이 훨씬 빨랐어요. 세 번째는 앞서 말한 도커 호출이 대기열에 걸려 자동화 스크립트가 15분 넘게 멈춘 사례입니다.
마무리: 다음 행동
지금 쓰는 코딩 에이전트가 파일과 네트워크에 어디까지 손댈 수 있는지 점검해본 적 없다면, 오늘 grith exec --로 그 에이전트를 한 번 감싸보는 것부터 시작해보세요. 승인 대기열에 뭐가 쌓이는지 하루만 지켜봐도 그동안 얼마나 넓은 권한을 감시 없이 자동화에 내줬는지 감이 잡힙니다.
자주 묻는 질문
Q. macOS나 윈도우에서도 지금 바로 쓸 수 있나요? A. 아니요. 안정 지원은 리눅스 x86_64(커널 4.8 이상)와 aarch64(커널 5.3 이상)뿐이고, macOS·윈도우는 별도 백엔드가 필요한 v2.0에서 지원될 예정입니다.
Q. 무료 버전과 유료 버전 기능 차이가 있나요? A. 저장소 코드는 오픈소스 라이선스로 공개돼 있고, 상위 기능은 같은 바이너리 안에 들어 있으며 서명된 라이선스로 잠금 해제하는 방식입니다.
Q. 대기열에서 아무도 응답하지 않으면 어떻게 되나요? A. CI처럼 사람이 없는 비대화형 세션은 실패 안전 원칙에 따라 자동으로 거부 처리됩니다.
Q. 릴리스가 조작되지 않았는지 어떻게 확인하나요? A. 각 릴리스는 체크섬과 서명, 소프트웨어 구성요소 명세, 빌드 출처 정보를 함께 배포하며 설치 스크립트가 자동으로 서명을 검증합니다.