
자작 후크와 Claude Code의 허가 체크 모두에 존재했던 동일한 사각지대——2>/dev/null 하나로 뚫리는 이야기
요약
Claude Code와 자작 후크의 위험 명령어 차단 메커니즘에서 발견된 보안 사각지대를 분석합니다. 리다이렉션 기호(2>/dev/null)를 사용하면 위험한 삭제 명령어가 필터링을 우회할 수 있음을 실측을 통해 증명합니다.
핵심 포인트
- 리다이렉션 기호 사용 시 명령어 차단 로직 우회 가능
- 문자열 기반 위험 판정 방식의 한계 지적
- 변수($HOME 등) 사용 대신 명시적 경로 지정 권장
- 백업 및 커밋을 통한 다층 방어 체계 구축 필요
Claude Code를 거의 24시간 내내 자율적으로 실행하고 있다. 셸(Shell)에도 접근할 수 있는 상태이므로, 가장 무서운 것은 실수로 넓은 범위를 삭제해 버리는 사고다. 나는 자작 후크(Hook)를 통해 위험한 삭제를 실행 직전에 차단하고, Claude Code 자체의 허가 메커니즘을 통해서도 위험한 조작을 막고 있다. 이중 망을 구축한 셈이었다.
얼마 전, 그 망의 한쪽에서 구멍을 발견했다. 그리고 며칠 후, 다른 한쪽—Claude Code 공식 허가 체크—에도 완전히 같은 형태의 구멍이 있었다는 것을 알게 되었다. 이 기사는 내 환경에서 종료 코드(Exit Code)까지 확인한 실측 결과와, 그 구멍이 공식 기능에도 존재했다는 사실을 나열한 기록이다.
내가 배포하는 무료 후크 모음인 cc-safe-setup의 핵심에는 위험한 삭제를 막는 후크가 있다. 여기에 각 명령어를 표준 입력(Standard Input)으로 전달하여, 차단(종료 코드 2)하는지 통과(0)시키는지 실측했다. 위험한 명령어는 단 한 번도 실행하지 않았다. 사용한 것은 npx cc-safe-setup으로 현재 설치되는 버전(npm으로 배포 중인 29.8.0, 2026년 7월 시점)이다. 후크는 업데이트될 수 있으므로, 동작은 검증한 시점의 것을 기준으로 한다.
| 명령어 | 종료 코드 | 결과 |
|---|---|---|
rm -rf ~ | 2 | 차단 |
rm -rf ~ 2>/dev/null | 0 | 통과 |
rm -rf "$HOME" 2>/dev/null; rm -f a | 0 | 통과 |
첫 번째 줄처럼 홈 디렉토리를 삭제하는 rm -rf ~는 제대로 차단된다. 그런데 두 번째 줄처럼 뒤에 2>/dev/null을 붙인 것만으로 통과되어 버린다. 똑같은 삭제임에도 불구하고, 에러 출력을 버리는 기호를 하나 붙였을 뿐인데 망을 빠져나간다. 세 번째 줄의 형태는 지어낸 이야기가 아니다. 홈 디렉토리 대신 임시 디렉토리를 삭제하려다가 변수가 실제 홈 디렉토리로 해석되어 서류나 이미지, 설정 등을 잃었다는 실제 사고 보고(GitHub 이슈 #75859)가 바로 이 형태다.
왜 빠져나가는가? 문자열로 위험을 판정하는 망은 '어디까지가 삭제 대상인가'를 글자 그대로 구분하려고 한다. 2>/dev/null은 셸에게는 '에러 출력을 버린다'는 별도의 지시이지만, 글자 그대로를 쫓는 망은 거기서 구분이 어긋난다. 셸이 실제로 명령어를 어떻게 해석하는지와 망이 글자를 어떻게 구분하는지가 어긋나 있는 것이다. 이 한 점의 틈을 리다이렉트(Redirect) 기호가 찌른다.
자작 망 이야기뿐이라면
라면 헛스윙을 해보며 확인한 뒤 실행한다. - 사라질 것을 전제로, 대피책을 만든다. 위험한 조작을 하기 전에, 대피용 브랜치(Branch)를 만들거나, 커밋(Commit)해 두거나, 백업(Backup)을 취한다. 망이 빠지더라도, 손실되는 것은 복구 가능한 범위 내로 한정된다.
- 대상을 명시적으로 좁힌다. 변수(Variable)에 의존하지 않는다. #75859의 핵심은 삭제 대상을 변수(
$HOME)에 맡겼다는 점이었다. 변수는 예상치 못한 값으로 해석될 수 있다. 삭제할 것이 확실한 서브 디렉터리라면,rm -rf ./build와 같이 상대적인 명시를 통해 오직 그 하나만을 대상으로 삼는다. - 설정, 실행, 복구를 독립시킨다. 허가 체크(Permission Check)나 자작 후크(Hook)와 같은 실행 직전의 망은 다층 방어 중 한 겹에 불과하다. 설정에서 위험한 도구의 호출을 허용하지 않는 층, 실행 직전에 멈추는 층, 망이 빠져도 복구할 수 있는 층을 서로 독립적으로 겹쳐 쌓는다.
솔직히 말하자면, 저의 무료 후크인 cc-safe-setup도 위 표와 같이 이 2>/dev/null 형태를 여전히 통과시켜 버린다(단독으로 발생하는 위험한 삭제는 막는다). 따라서 "이것을 넣으면 안전하다"라고는 말하지 않겠다. 가장 발생하기 쉬운 형태를 막는 한 겹의 망으로서 사용하고, 그 위에 층을 쌓아 올리길 바란다. 글자 그대로의 형태에 의존하는 한 겹의 망은 공식적인 것이든 자작이든, 작성 방식을 바꾸면 빠져나간다. 그것을 전제로 한 다층 방어만이 당신의 데이터를 지켜준다.
자율적으로 실행되는 Claude Code의 사고를 실행 직전에 막아주는 설정과 후크의 모음은 무료로 배포하고 있다(npx cc-safe-setup). 이번 사례와 같은 "한 겹의 망이 가진 한계와, 층으로 방어하는 구체적인 구성 방법"을 실제 사고 기록과 함께 체계적으로 정리한 책(¥800)도 있다.
-
무료 설정 및 후크:
npx cc-safe-setup -
Claude Code 사고 방지 핸드북(¥800): https://zenn.dev/yurukusa/books/6076c23b1cb18b
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기