Claude Code에게 '이 리포지토리를 커밋하고 push 해줘'라고 맡겼을 때, 머릿속에 불안감이 떠오른다. 프로젝트의 .env 파일,
우연히 남겨둔 credentials.json,
~/.ssh 같은 키들—이러한 비밀 파일들이 한꺼번에 커밋되어 공개 리포지토리에 push되지 않을까.
결론부터 말한다. 이것은 가상의 이야기가 아니라, 실제로 발생했다는 보고가 있다. 그리고 지침서에 '커밋하지 마'라고 적는 것만으로는 막을 수 없다. 막고 싶다면, 실행 직전의 명령 자체를 확인하고 거부하는 메커니즘이 필요하다. 아래는 그 메커니즘이 정말로 멈추는지, 종료 코드를 측정하여 내 환경에서 확인한 기록이다.
Issue #2142(OPEN)에서는 심각도를 CRITICAL로 보고하며 다음과 같이 전했다. CLAUDE.md에 '🚨 NEVER COMMIT API KEYS TO VERSION CONTROL (API 키를 절대로 버전 관리 시스템에 커밋하지 마라)'라고 명시하고, 사용자가 '그 CLAUDE.md를 읽고 작업해 달라'고 부탁했음에도 불구하고, 어시스턴트가 실제 API 키와 인증 정보를 반복적으로 공개 GitHub 리포지토리에 커밋했다는 것이다. 같은 세션 내에서 여러 번 재발했다고도 언급되었다.
즉, 두려워했던 일이 조건이 갖춰지면 실제로 일어날 수 있다. 여기서 중요한 것은 '왜 지침만으로는 멈추지 않았는지'이다.
Issue #34132가 지적하듯이, CLAUDE.md나 .claude/rules/에 적은 규칙은 어디까지나 조언일 뿐, 강제하는 메커니즘이 아니라는 보고가 있다. 모델은 그것을 읽지만, 읽었다고 해서 따르지 않을 때가 있다. #2142는 바로 그 실제 사례이다.
그렇다면 방어책을 '모델이 읽을 수도 있는 문장' 쪽에 두어도, 무시될 때는 무시된다. 방어는 모델의 기분에 의존하지 않는 곳—실제로 명령이 실행되기 직전—에 두어야만 한다. Claude Code의 PreToolUse 훅은 Bash에서 명령이 실행되기 직전에 개입하여, 그 명령어 문자열을 보고 위험하면 종료 코드 2를 반환하여 실행 자체를 막을 수 있다. 문장 지침과는 달리, 이것은 무시되지 않는다.
내가 배포하는 무료 훅 모음 cc-safe-setup에는 이 용도의 핵심 훅 secret-guard가 포함되어 있다. 내용만 읽는 것만으로는 신뢰할 수 없기 때문에, 비밀을 누설하는 형태의 명령어를 실제로 훅에 전달하여, 내 임시 git 리포지토리에서 실행해보고 종료 코드를 측정했다 (2 = 실행 직전에 차단, 0 = 그대로 통과).
훅에는 `{
| 입력한 명령 | 종료 코드 | 통과하는 이유 |
|---|
git commit -m wip | 0 | 이 훅은 git add 단계를 확인한다. 이미 스테이징(Staging)된 비밀 정보는 commit / push 단계에서는 검사하지 않는다 |
git push origin main | 0 | 위와 동일. push 자체는 확인하지 않는다 |
git add .npmrc | 0 | .npmrc는 인증 토큰을 포함하지만, 이름이 패턴에 일치하지 않는다 |
git add secrets.yaml | 0 | 다른 이름의 비밀 파일은 이름으로 포착되지 않는다 |
git add config.json (내용이 API 키인 경우) | 0 | 훅은 명령 문자열을 확인한다. 파일의 내용은 확인하지 않는다 |
내 환경에서의 실측을 통해 알 수 있는 점은 명확하다. 이 훅은 가장 발생하기 쉬운 유출 형태(git add .env 및 git add -A)를 실행 직전에 확실히 차단한다. 하지만 유출을 불가능하게 만들지는 않는다. 다른 이름의 비밀 파일, 무해한 이름의 파일에 붙여넣은 비밀, 이미 스테이징된 것들은 이 한 장의 훅만으로는 모두 방어할 수 없다.
따라서 훅은 하나의 계층(Layer)으로 사용하고, 다음의 운영 방식과 조합하는 것이 현실적이다.
- 비밀 파일은 반드시
.gitignore에 포함한다 (훅은 그 전 단계의 마지막 그물이다).
git add -A를 습관화하지 말고, git add src/ package.json과 같이 수정한 파일을 명시적으로 지정한다.
- 실제 비밀 정보를 추적 대상 파일(
config.json 등)에 직접 작성하지 않는다.
"CLAUDE.md에 적었는데 지켜지지 않는다"와 "실행 직전에 정말로 차단된다"의 차이는 방어선을 어디에 두느냐의 차이다. #2142는 전자의 한계를, 내 환경에서의 실측은 후자의 작동 방식과 그 한계를 보여준다. 지시는 무시될 수 있지만, 종료 코드 2는 무시되지 않는다.
위의 secret-guard는 cc-safe-setup의 핵심 훅으로서 기본적으로 포함되어 있다.
도입하면 git add .env나 .env가 있는 상태에서의 git add -A가 실행 직전에 차단된다. 내용과 검증 절차는 GitHub에 공개되어 있다. → https://github.com/yurukusa/cc-safe-setup
비밀 유출뿐만 아니라, 커밋되지 않은 작업의 소실, 비용 폭주, 중단되었어야 할 프로세스의 폭주 등 Claude Code 운영 중에 실제로 발생한 사고들을 원인과 수동 방어책별로 정리한 사고 방지 서적을 출간했다(¥800). 이 기사에서 다룬 비밀 유출 문제도 더 깊이 있게 다루고 있다. → https://zenn.dev/yurukusa/books/6076c23b1cb18b