Claude Code '다시 묻지 않기'가 비밀번호까지 저장…절반 가까이 Claude가 GitHub에 커밋
Claude Code에서 '다시 묻지 않기'를 고르면 명령에 든 DB 비밀번호까지 설정 파일에 평문으로 남습니다. Apiiro가 공개 GitHub에서 이런 파일 1,122개와 실제 비밀 1,379개를 찾았고, 보안 스캐너 둘 다 215개를 놓쳤습니다.
- '다시 묻지 않기'를 고르면 명령 속 비밀번호가 파일에 평문으로 남습니다.
- 공개 GitHub에서 이런 파일 1,122개, 비밀 1,379개가 나왔습니다.
- 실제 비밀이 든 저장소 절반 가까이는 Claude가 직접 커밋했습니다.
Claude Code 사용자가 권한 확인 창에서 "다시 묻지 않기"를 고른 명령이 데이터베이스 비밀번호와 API 키를 담은 채 공개 GitHub 저장소 1,994곳에 올라가 있는 사실이 확인됐습니다. 보안 업체 Apiiro가 11월 5일 낸 조사 보고서에 따르면 이렇게 드러난 실제 비밀은 2,539개입니다. 의료기록 앱의 데이터베이스 소유자 비밀번호, 공개 서버의 루트 SSH 비밀번호도 섞여 있었습니다.
Claude Code를 쓰는 개발자라면 하루에도 몇 번씩 누르는 버튼입니다. 그 버튼이 무엇을 어디에 적는지 아는 사람은 많지 않았습니다.
버튼 하나가 비밀번호를 파일에 적는다
Claude Code는 터미널 명령을 실행하기 전에 매번 허락을 구합니다. 선택지는 "예", "예, 다시 묻지 않기", "아니요" 등입니다. 두 번째를 고르면 다음부터 같은 명령은 묻지 않고 실행합니다. 공식 문서에 따르면 이 승인은 저장소 단위로 영구 저장되고, 위치는 저장소 루트의 .claude/settings.local.json입니다.
문제는 저장되는 내용입니다. Claude Code는 승인한 명령 문자열을 그대로 허용 규칙으로 적습니다. 스테이징 서버 로그인이 왜 안 되는지 봐 달라고 하면 Claude는 설정 파일에서 접속 정보를 읽어 PGPASSWORD=비밀번호 psql -h 호스트 ... 같은 명령을 제안합니다. 비밀번호가 없으면 명령이 동작하지 않으니까요. 여기서 "다시 묻지 않기"를 누르면 비밀번호가 든 명령 한 줄이 JSON 파일에 평문으로 남습니다.

Anthropic도 이 파일이 밖으로 나가면 안 된다는 걸 압니다. 설정 문서는 Claude Code가 이 파일을 처음 만들 때 사용자 PC의 전역 git 제외 목록에 **/.claude/settings.local.json을 추가한다고 설명합니다. 그 PC에서 하는 커밋에는 이 파일이 빠집니다.
Apiiro는 이 보호가 저장소가 아니라 PC에 걸려 있어서 빈틈이 생긴다고 짚었습니다.
- 파일이 생긴 뒤에 git 저장소가 된 폴더는 보호받지 못합니다.
- 다른 PC로 클론하면 그 PC의 제외 목록에는 이 규칙이 없습니다.
- 이미 커밋된 파일은 제외 목록에 넣어도 계속 추적됩니다.
- 저장소 자체
.gitignore에는 아무것도 추가되지 않아서 프로젝트를 따라다니는 보호 장치가 없습니다.
Apiiro는 이 동작이 모델이 아니라 Claude Code 프로그램의 동작이라고 밝혔습니다. 최신 모델인 Opus 5.5와 Fable 5.1에서도 똑같이 재현됐습니다. 코딩 에이전트 16종의 문서를 비교했더니, 기본 설정에서 승인한 명령 전체를 프로젝트 파일에 쓰는 것으로 확인된 도구는 Claude Code 하나였습니다.
공개 GitHub에서 나온 비밀 1,379개
Apiiro는 11월 1일부터 3일까지 GitHub 코드 검색으로 공개 저장소의 이 파일을 전부 내려받았습니다. 103,617개 저장소에서 104,185개가 나왔고, 그중 1,122개(1.1%)에 실제 비밀이 들어 있었습니다. 고유한 비밀은 1,379개입니다.

셋 중 하나 넘게는 데이터베이스를 바로 여는 열쇠였습니다. 데이터베이스 비밀번호가 379개, Supabase 서비스 역할 키가 122개입니다. AI 모델 API 키도 149개였습니다. Apiiro가 확인한 피해 조직은 63곳이고, 대표 사례는 이렇습니다.
- 데이터베이스 업체 자사의 관리 권한 클라우드 키(만료 기한 없음).
- 의료기록 앱을 만든 IT 서비스 회사의 클라우드 Postgres 소유자 비밀번호.
- 결제 스타트업의 Postgres 비밀번호, 소프트웨어 에이전시의 Square 운영 토큰.
- 별 1,000개가 넘는 오픈소스 프로젝트의 OpenAI 형식 API 키.
- 공개 서버의 루트 SSH 명령을 영구 승인한 대학 저장소.
Apiiro는 11월 2일과 3일 각 조직에 알렸고, 한 곳은 키가 실제로 살아 있었다고 확인했습니다. 보고서는 자격 증명을 직접 써 보지는 않았다고 밝혔습니다. 그래서 나머지가 지금도 유효한지는 알 수 없습니다.
누가 커밋했는지도 추적했습니다. 실제 비밀이 든 저장소 1,105곳 중 539곳에서 Claude가 공동 저자로 기록된 커밋이 이 파일을 바꿨습니다. Sonnet 4.5부터 Opus 5.5까지 최근 모델이 모두 나옵니다. 다만 Claude가 커밋에 참여했다고 해서 비밀까지 Claude가 넣었다고 볼 수는 없습니다.
한 번 올라간 파일은 오래 남았습니다. 비밀이 든 저장소에서 이 파일이 처음 커밋된 뒤 지난 기간은 중간값으로 217일입니다. 118개 저장소는 1년이 넘었습니다. 포크 211개가 같은 비밀을 복사해 갔고, 파일을 지운 뒤 git 기록에만 남은 비밀도 509개 저장소에서 734개 나왔습니다. 파일을 지워도 해결되지 않는다는 얘기입니다.
보안 스캐너 두 개가 모두 놓친 215개
비밀 유출 검사에 많이 쓰는 오픈소스 도구 gitleaks와 TruffleHog를 1,122개 파일에 돌렸습니다. gitleaks가 564개, TruffleHog가 643개를 잡았고 215개는 둘 다 놓쳤습니다. 다섯 개 중 하나꼴입니다.
이유는 비밀번호의 생김새입니다. 이런 스캐너는 sk-, AKIA 같은 접두사나 길고 무작위한 문자열을 찾습니다. 명령 중간에 사람이 타이핑한 비밀번호는 평범한 단어처럼 보입니다. PGPASSWORD=, sshpass -p, mysql -p 뒤에 오는 값이나 curl 명령의 Authorization: Bearer 헤더가 그렇습니다.
같은 일은 에이전트가 실행한 명령을 기록하는 다른 파일에서도 벌어졌습니다.
| 파일 | 조사한 수 | 실제 비밀 |
|---|---|---|
팀이 일부러 커밋하는 공유 설정 .claude/settings.json | 76,011개 | 298개 파일 |
| 에이전트 대화 기록(.specstory, aider, Cursor 내보내기) | 2,523개 | 87개 저장소, 120개 파일 |
| 에이전트 메모리 파일(MEMORY.md 등) | 1,200개 | 9개 저장소 |
| 인수인계·배포 메모 | 2,095개 | 33개 파일 |
| VS Code Copilot 자동 승인 설정 | 173개 | 9개 저장소 |
인수인계 메모에서 나온 비밀의 3분의 1은 에이전트가 직접 쓴 메모였습니다. GitHub 밖도 비슷했습니다. Hugging Face Spaces 31,053개 중 126개에 이 파일이 있었고, 그중 하나에는 데이터베이스 서비스 키가 들어 있었습니다.
GitHub에 올라가지 않았다고 안전한 것도 아닙니다. 2025년 9월 npm 패키지를 감염시킨 Shai-Hulud 웜은 피해자 PC에서 TruffleHog를 돌려 비밀을 긁어 갔습니다. Apiiro가 찾은 파일 1,122개 중 643개는 그 스캐너에 걸립니다. 7개월 만에 다시 악성 배포된 LiteLLM처럼 개발자 PC의 자격 증명을 노리는 공급망 공격이 잇따르고 있습니다. 공격자에게는 평문 JSON 파일 하나가 정리된 열쇠 꾸러미가 됩니다.
2025년 8월부터 신고됐지만 답이 없었다
이 동작은 새로 발견된 것이 아닙니다. 2025년 8월 Claude Code 저장소에 "자격 증명이 든 승인 명령이 평문 그대로 settings.local.json에 저장된다"는 이슈 #5544가 올라왔습니다. 이 이슈는 Anthropic 답변 없이 2026년 1월 비활성 상태로 자동 종료됐습니다.
Apiiro가 꼽은 관련 이슈는 네 건이고, 셋은 자동 종료나 중복 처리로 닫혔습니다. VS Code 확장이 '항상 허용'을 공유 설정 파일에 쓴다는 이슈 #91270은 보고서가 나온 11월 5일 당일 비활성 이유로 자동 종료됐습니다. 이 글을 쓰는 시점까지 Anthropic의 공식 입장은 확인되지 않았습니다.
보고서를 읽을 때 걸러 볼 점도 있습니다. Apiiro는 보안 제품을 파는 회사입니다. 또 '실제 비밀'은 알려진 키 형식이거나 공개 호스트 옆에 놓인 값을 뜻하고, 실제로 접속되는지 확인한 것은 아닙니다. 분류 마지막 단계에는 규칙 검사와 함께 별도 LLM 검토자를 썼습니다. 그렇다 해도 동작 자체는 공식 문서와 GitHub 이슈로 확인됩니다.
내 저장소에 남았는지 확인하는 법
요금제와 지역에 관계없이 모든 Claude Code 사용자에게 해당하며 한국 사용자도 예외가 아닙니다. 아래 중 하나라도 맞으면 확인해 보세요.
| 상황 | 위험 |
|---|---|
| 명령에 비밀번호·토큰이 들어간 채 "다시 묻지 않기"를 고른 적이 있다 | PC의 settings.local.json에 평문으로 남음 |
| 그 폴더를 나중에 git 저장소로 만들었거나 다른 PC에서 클론했다 | 전역 제외가 적용되지 않아 커밋될 수 있음 |
| Claude에게 "전부 커밋해 줘"를 맡긴 적이 있다 | 파일이 커밋에 섞였을 수 있음 |
팀 공유 .claude/settings.json에 승인 규칙을 넣어 쓴다 | 처음부터 커밋되는 파일 |
저장소 루트에서 이 파일이 한 번이라도 커밋됐는지, 지금 파일에 비밀번호가 든 규칙이 있는지는 다음 명령으로 볼 수 있습니다.
git log --all --oneline -- .claude/settings.local.json .claude/settings.json
grep -nE "PGPASSWORD=|sshpass -p|mysql .*-p|Bearer |://[^ ]*:[^ ]*@" .claude/settings.local.json
나온 것이 있으면 비밀번호부터 바꾸고 파일 정리는 그다음입니다. 포크와 클론에는 이미 복사돼 있기 때문입니다. 추적 중인 파일은 git rm --cached .claude/settings.local.json으로 빼고 저장소 .gitignore에도 이 경로를 넣습니다. 앞으로는 비밀번호를 명령에 직접 넣지 말고 $DB_URL 같은 환경 변수로 참조하게 하면, 규칙에는 변수 이름만 남습니다. 승인할 때도 문자 그대로의 명령 대신 Bash(npm run *) 같은 패턴 규칙을 고르면 됩니다.
오늘 하나만 한다면, Claude Code로 데이터베이스나 서버에 접속해 본 프로젝트를 골라 위의 git log 명령부터 돌려 보세요. 결과가 비어 있으면 PC의 파일만 정리하면 되고, 커밋 기록이 나오면 그 저장소에 들어갔던 자격 증명은 전부 교체 대상입니다.