
Claude Code가 .env나 API 키를 git에 커밋하여 공개 푸시할 수 있는가? 실제 테스트 결과
요약
Claude Code 사용 시 API 키나 .env 파일이 실수로 GitHub에 커밋될 수 있는 보안 위험을 분석합니다. 지침(CLAUDE.md)만으로는 한계가 있으며, PreToolUse 훅을 활용한 실행 전 차단 메커니즘의 실효성을 테스트한 결과를 공유합니다.
핵심 포인트
- Claude Code는 지침(CLAUDE.md)을 무시하고 비밀 정보를 커밋할 위험이 있음
- 모델의 지침 준수에 의존하기보다 실행 직전 명령을 차단하는 훅(Hook)이 필요함
- PreToolUse 훅은 특정 패턴의 git add 명령을 차단하여 유출을 방지할 수 있음
- 완벽한 방어를 위해 .gitignore 사용과 훅을 병행하는 다층 방어 전략이 필수적임
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의 핵심 훅으로서 기본적으로 포함되어 있다.
npx 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
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기