AI 코딩 에이전트에 shell 권한을 주면 생산성이 크게 올라간다.
그만큼 위험도 커진다.
특히 다음 명령은 한 번 잘못 실행되면 복구가 어렵다.
git reset --hard
git clean -fd
git push --force
rm -rf
git gc --prune=now중요한 것은 모델에게 “조심해”라고 말하는 것이 아니라 실행 경계에서 막는 것이다.
1. 사후 cleanup은 방어가 아니다
처음에는 세션 종료 후 사고 파일을 정리하는 hook을 생각할 수 있다.
하지만 이미:
명령 실행
→ 파일 삭제
→ reflog 정리
→ cleanup순서라면 늦다.
파괴 명령은 실행 전에 차단해야 한다.
2. PreToolUse 패턴
구조는 단순하다.
Agent가 command 생성
↓
PreToolUse
↓
command 검사
↓
BLOCK 또는 ALLOW이렇게 하면 모델이 위험한 명령을 만들어도 실제 shell까지 도달하지 않는다.
3. 문자열 하나만 보고 막으면 안 된다
예를 들어:
git clean -n은 실제 삭제가 아니라 dry-run이다.
그래서 blacklist는 구체적이어야 한다.
차단 후보:
git reset --hard
git clean -fd
git push --force
rm -rf허용 후보:
git clean -n
git reflog
git gc --auto
git rm --cached허용 목록은 prefix가 아니라 플래그까지 포함한 형태로 비교해야 한다. git gc를
prefix로 허용하면 위에서 차단 대상으로 꼽은 git gc --prune=now가 그대로 통과한다.
차단 목록을 아무리 잘 써도 허용 목록이 그것을 되돌린다.
4. Guardrail도 테스트해야 한다
보안 hook을 만들었으면 두 종류를 모두 테스트한다.
위험 명령 → 실제로 차단되는가
정상 명령 → 잘못 차단되지 않는가false negative만 보는 것이 아니라 false positive도 본다.
5. Escape hatch는 다중 조건으로
정말 필요한 경우 우회할 수는 있어야 한다.
하지만 단순한 환경변수 하나는 너무 약하다.
더 나은 방법은 다음을 함께 요구하는 것이다.
승인 artifact
repository path
timestamp
명령 종류운영에서 빠지기 쉬운 우회 경로
파괴 명령을 막을 때 가장 흔한 실수는 명령의 첫 토큰만 검사하는 것이다. 실제 shell에서는 wrapper나 하위 shell을 통해 같은 명령이 실행될 수 있다.
bash -c "git reset --hard"
powershell -Command "git clean -fd"따라서 guard는 단순 문자열 포함 여부보다 실제로 실행될 command의 의미를 보는 편이 낫다. 완전한 shell parser가 아니더라도 nested command, command chaining, alias 정도는 별도 테스트 케이스로 넣어야 한다.
Git 명령은 위험도별로 나누는 편이 낫다
모든 Git 명령을 막으면 agent의 효율이 크게 떨어진다. 대신 다음처럼 위험도를 나누면 운영하기 쉽다.
LOW
- git status
- git diff
- git log
MEDIUM
- git add
- git commit
- git checkout
HIGH
- git reset --hard
- git clean -fd
- git push --forceLOW는 자동 허용, MEDIUM은 정책에 따라 허용, HIGH는 기본 차단 또는 사용자 승인으로 처리할 수 있다.
프롬프트와 실행 정책을 분리한다
다음 두 문장은 역할이 다르다.
프롬프트: 파괴 명령을 사용하지 마라.
실행 정책: 이 명령은 실행할 수 없다.첫 번째는 행동 지침이고 두 번째는 기술적 통제다. 안전성의 최종 책임은 후자에 두는 편이 낫다.
실무 체크리스트
[ ] destructive command 목록 정의
[ ] dry-run 예외 정의
[ ] wrapper/nested command 테스트
[ ] 차단 케이스 테스트
[ ] 정상 명령 허용 테스트
[ ] 예외 승인 범위 제한
[ ] 승인 및 차단 로그 기록결론
AI agent 안전성은 “모델이 실수하지 않는 것”에 의존하면 안 된다.
모델이 실수해도 치명적 명령이 실행되지 않도록 시스템 경계를 만드는 것이 더 중요하다.
공식 문서 참고
- Claude Code Hooks / PreToolUse: https://code.claude.com/docs/en/hooks