읽는 데 8분
Claude Code 승인 파일, Git에서 뺐어도 배포 묶음엔 남을 수 있어요
Git에서 무시하도록 해 둔 파일 하나를 두 방식으로 묶었어요. git archive HEAD로 만든 묶음에는 없었는데, 작업 폴더를 tar로 묶자 들어갔어요. 시험에 쓴 건 실제 키가 아닌 가상 .claude/settings.local.json이에요. 커밋에서 빼는 것과 배포물에서 빼는 것은 별개예요.
이 차이를 확인한 계기는 보안 업체 Apiiro의 Claude Code 조사예요. 11월 5일 공개한 연구에서, 공개 GitHub의 개인 설정 파일 104,185개 중 1,122개에 비밀정보가 있다고 분류했어요. 연구진이 그 자격증명을 사용하거나 현재 유효한지 시험한 수치는 아니에요.
실행을 허용한 명령이 파일에 남아요
Claude Code가 명령 실행을 물을 때 “Yes, and don't ask again”을 고르면, 그 승인은 프로젝트의 .claude/settings.local.json에 allow 규칙으로 저장돼요. Apiiro가 확인한 문제는 비밀번호나 토큰을 직접 넣은 명령 문자열 전체가 규칙에 남을 수 있다는 거예요. 명령에 직접 적은 비밀 값이 승인 규칙에도 남을 수 있는 셈이죠.
Anthropic 문서에 따르면 Claude Code는 Git 저장소에서 이 파일을 처음 쓸 때, 아직 무시되지 않았다면 사용자의 전역 Git 제외 목록에 넣어요. 이 목록은 사용자 환경에 있고, 저장소의 .gitignore와는 달라요. 이미 Git이 추적하는 파일에는 무시 규칙을 추가해도 소용없어요.

같은 파일로 제외와 묶기를 나눠 시험했어요
빈 저장소와 가상 JSON을 Linux에서 만들었어요. Git 2.39.5와 GNU tar 1.34를 썼고, Claude Code의 승인 화면 자체를 실행한 시험은 아니에요.
먼저 전역 제외만 설정한 저장소에서는 git add .를 해도 파일이 올라가지 않았어요. 그 저장소를 전역 제외 설정이 없는 환경에 복제하고, 같은 경로의 로컬 파일을 새로 만들자 이번에는 커밋 대기 목록에 들어갔어요. 무시된 파일이 clone으로 복사된 게 아니라, 제외 규칙이 함께 전달되지 않은 결과예요.
저장소의 .gitignore를 커밋해서 공유하면 복제본에서도 새 로컬 파일을 제외했어요. 반대로 파일을 먼저 커밋한 뒤 .gitignore를 추가한 경우에는, 그 파일의 수정 내용도 계속 커밋 대기 목록에 들어갔어요.
마지막에는 .gitignore가 정상적으로 파일을 제외하는 같은 폴더를 묶어 봤어요. 묶음 파일은 시험 폴더 밖에 만들었어요.
# 작업 폴더 기준. .git 디렉터리만 따로 제외했어요.
tar --exclude=./.git -cf ../folder.tar .
# 현재 커밋 기준
git archive --format=tar --output=../commit.tar HEAD
| 묶는 방법 | 가상 로컬 설정 파일 포함 | 이유 |
|---|---|---|
| 폴더 전체를 위 tar 명령으로 묶기 | 포함 | Git의 제외 목록을 적용하지 않고 폴더를 묶었어요 |
| 위 Git archive 명령으로 HEAD 묶기 | 제외 | 해당 파일이 현재 커밋에 없었어요 |
Git archive도 비밀정보 검사기는 아니에요. 선택한 커밋에 민감한 파일이 있으면 묶음에 들어갈 수 있어요. 여기서 차이를 만든 건 파일 확장자가 아니라 폴더를 입력으로 삼았는지, 커밋을 입력으로 삼았는지예요.
Docker도 별도 확인이 필요해요. 공식 문서는 로컬 디렉터리를 빌드 입력으로 쓸 때, 빌더로 보내지 않을 파일을 입력 폴더 루트의 .dockerignore에서 제외하도록 설명해요. 로컬 폴더로 빌드하며 COPY .를 쓴다면 Git 제외만 믿으면 안 돼요. Dockerfile 전용 ignore 파일이 있으면 루트 .dockerignore보다 우선하므로 그쪽도 봐야 해요.
내 저장소에서는 무엇부터 볼까요
이미 파일이 외부에 나갔고 비밀 값이 있었다면, 키를 폐기하거나 교체하는 일이 먼저예요. 파일 삭제나 추적 해제로 이전 커밋과 다른 사람의 복사본이 지워지지는 않아요.
저장소 루트에서 다음 명령은 현재 추적 여부와 로컬에서 볼 수 있는 이력을 확인하는 데 쓸 수 있어요. 파일 내용이나 키 자체를 출력하지 않아요.
git ls-files -- .claude/settings.local.json
git log --all --oneline -- .claude/settings.local.json
추적 중이면 로컬 변경과 커밋 대기 상태를 먼저 확인한 뒤 git rm --cached -- .claude/settings.local.json으로 추적에서 빼고, 저장소의 .gitignore에 경로를 넣어요. 이 명령은 로컬 파일을 남겨요. 수정 충돌로 거부되면 강제로 밀어붙이지 말고 변경 내용을 먼저 정리해야 해요. 제외 규칙과 추적 해제도 커밋해야 저장소에 반영돼요.
그다음은 실제 배포 방식에 맞춰 나눠 봐요.
- 폴더를 압축해 보내면, 완성된 묶음의 파일 목록에서 로컬 설정이 빠졌는지 확인해요.
- 로컬 폴더로 Docker 이미지를 만들면, 적용되는
.dockerignore에도.claude/settings.local.json을 제외해요. - 개인 승인 파일을 정리하면서 팀 공유용
.claude/settings.json까지 무조건 삭제하지는 않아요. 공유 파일도 비밀 값이 있는지는 별도로 봐야 해요.
이후 승인할 명령에는 비밀 값을 직접 쓰는 대신 비밀정보 관리 도구의 환경변수 이름을 참조하는 방식으로 바꿔요. 이미 저장된 규칙에 값이 남았는지도 점검하고요. 커밋에 없다는 확인 뒤에는, 내가 실제로 내보내는 묶음도 한 번 더 보면 돼요.
확인한 범위
- 기준일: 2026-11-09
- 직접 한 것: 가상 설정 파일로 전역 제외, 새 복제본, 저장소 제외, 추적 중인 파일, 폴더 tar와 Git archive 결과를 Linux의 Git 2.39.5와 GNU tar 1.34로 비교했어요. Anthropic·Git·Docker 문서의 적용 범위도 대조했어요.
- 읽은 것: Apiiro 연구와 11월 8일 갱신, Claude Code 설정 문서, Git ignore/archive 문서, Docker 빌드 입력 문서, 같은 사건의 한국어 글 두 편이에요.
- 확인하지 못한 것: Claude Code 실제 승인 UI와 현재 수정 여부, 실제 자격증명의 유효성은 확인하지 않았어요. Docker 이미지와 npm 패키지를 직접 만들지는 않았어요.
출처


Git의 세부 동작은 gitignore와 git archive 문서도 대조했어요.



