
당신의 CLAUDE.md는 GitHub에 공개되어 있습니다 — 지금 즉시 .gitignore에 추가하세요
요약
Claude Code 사용 시 생성되는 CLAUDE.md 파일이 GitHub에 그대로 노출되어 사내 기밀이 유출되는 사례가 빈번합니다. 이 파일은 AI를 위한 시스템 프롬프트 역할을 하므로, 보안을 위해 반드시 .gitignore에 추가해야 합니다.
핵심 포인트
- CLAUDE.md는 AI에게 전달하는 핵심 컨텍스트 파일임
- 사내 명명 규칙, DB 스키마, API 키 등 민감 정보 포함 위험
- GitHub Search를 통해 수만 건의 파일이 이미 노출된 상태
- 보안 유지를 위해 반드시 .gitignore에 등록 권장
GitHub Search에서 path:CLAUDE.md라고 입력해 보세요.
5만 건 이상의 리포지토리(Repository)에서 CLAUDE.md가 그대로 공개되어 있습니다. 그중에는 사내 명명 규칙(Naming Convention), 운영 DB(Production DB)의 스키마, 검증용 API 키의 파편, 미공개 제품의 내부 코드네임까지, 본래 커밋(Commit)해서는 안 되는 정보가 통째로 노출되어 있는 사례가 산견됩니다.
저도 Claude Code를 매일 사용하고 있기에 알 수 있는 사실이지만, CLAUDE.md는 "AI에게 전달하는 자신의 취급 설명서"입니다. 프롬프트(Prompt)에 매번 쓰고 싶지 않은 지시 사항을 전부 담아둡니다. 그렇기 때문에 작성하는 내용은 점점 사내 지식(Knowledge)에 가까워지게 됩니다.
그리고 대부분의 사람이 그것을 .gitignore에 추가하지 않고 있습니다.
이 기사에서는 왜 CLAUDE.md를 커밋해서는 안 되는지, 이미 공개해 버렸다면 어떻게 취소해야 하는지, AI 관련하여 .gitignore에 추가해야 할 파일은 무엇인지에 대해 실례를 바탕으로 정리합니다.
만약을 위해 CLAUDE.md가 무엇인지 정리하겠습니다.
이것은 Claude Code가 프로젝트 루트(Project Root)에서 자동으로 읽어들이는 컨텍스트(Context) 파일입니다. 글로벌(~/.claude/CLAUDE.md)과 프로젝트 단위의 2계층으로 동작하며, 세션 시작 시 Claude가 반드시 참조합니다.
즉, CLAUDE.md에 작성한 내용은 매번 Claude에게 전달하는 시스템 프롬프트(System Prompt)와 동일합니다.
엔지니어가 이곳에 쓰기 쉬운 정보들을 나열해 보겠습니다.
- 사내 라이브러리의 명명 규칙 (Naming Convention)
- 운영 DB의 테이블 구조와 관계 (Relation)
- 내부 API 엔드포인트 (Endpoint) 목록
- 보안 정책 (IP 화이트리스트, 인증 방식)
- 리팩터링 (Refactoring) 중인 영역과 현재 작업 상태
- 미공개 프로덕트의 코드네임
- 검증용 테스트 자격 증명 (Test Credential)이나 API 키의 파편
작성하는 순간에는 "Claude에게 전달할 뿐이니까"라고 생각합니다. 하지만 리포지토리에 그대로 커밋하면, 그것은 GitHub을 통해 전 세계로 배포되는 사내 문서가 됩니다.
검증해 보았습니다. 2026년 5월 시점의 GitHub Search에서 다음 쿼리(Query)를 실행한 결과입니다.
| 쿼리 | 대략적인 히트 건수 |
|---|---|
path:CLAUDE.md | 5만 건 초과 |
path:CLAUDE.md "API" | 1.2만 건 초과 |
path:CLAUDE.md "production" | 7,000건 초과 |
path:CLAUDE.md "internal" | 4,000건 초과 |
path:.cursorrules | 3.5만 건 초과 |
path:AGENTS.md | 8,000건 초과 |
이 숫자에는 물론 "OSS의 문서용 CLAUDE.md", "샘플 템플릿", "개인 블로그용" 등 유출 리스크가 없는 것도 포함됩니다.
하지만 path:CLAUDE.md "production"으로 나오는 리포지토리의 내용을 살펴보면, 명백히 업무용인 것들이 상당수 섞여 있습니다. 운영 환경의 URL, 사내 Slack 채널명, 미공개 API 스키마가 태연하게 적혀 있는 것들이 있었습니다.
제가 확인할 수 있었던 범위만으로도, 이것은 검색 결과의 빙산의 일각입니다.
본 기사에는 구체적인 리포지토리 이름이나 URL을 싣지 않습니다. 유출된 측의 불이익이 될 수 있기 때문입니다. 다만, 누구나 동일한 쿼리로 재현할 수 있습니다. GitHub 계정만 있다면 30초 만에 확인할 수 있는 사실입니다.
실제로 GitHub Search로 살펴본 범위 내에서, CLAUDE.md로부터 유출되는 정보의 패턴을 5가지로 정리합니다. 익명화 및 추상화된 형태로 작성하겠습니다.
## 개발 환경
- API: https://api-staging.internal.example.com
- 관리 화면: https://admin-dev.example.com
...
사내 DNS 명이나 배스천 호스트(Bastion Host)의 호스트 명이 그대로 적혀 있는 패턴. 공격자의 정찰(Reconnaissance) 단계와 직결됩니다.
## 명명 규칙
- 마이크로서비스(Microservice)의 접두사는 `xxx-` (사명 앞글자)
- 내부 프로젝트 코드: Project Atlas, Phoenix, Hermes
...
사내 코드네임이 적혀 있으면, 미발표 프로덕트의 존재가 드러납니다. M&A 협상 중인 안건명이 유출된 사례도 (국외에서) 보고된 바 있습니다.
## 테스트용 credential
- 개발용 API 키: ak_test_xxxxxxxxxxxxx (※ 커밋 금지)
- IAM Role: arn:aws:iam::123456789012:role/dev-claude-access
...
「※ 커밋 금지」라고 쓰면서도 커밋되는 것은 아이러니하지만, 실제 사례로 존재합니다. AWS 계정 ID만으로도 공격자의 타겟팅에 이용될 수 있습니다.
## 계산 규칙
- 월간 플랜: 기본 요금 + 이용량 × 단가 - 법인 할인(계약 연수 × 2%, 최대 10%)
- 탈퇴 플로우: 30일의 쿨링오프(Cooling-off) → free 플랜으로 자동 강등 → 90일 후 완전 삭제
요금 체계나 고객 라이프사이클(Customer Lifecycle)이 그대로 기술되어 있는 케이스. 경쟁사 분석의 좋은 재료가 됩니다.
## 연락처
- 백엔드 책임자: @yamada (사내 Slack)
- 인프라: @sato (PagerDuty escalation)
사내 계정과 역할(Role)의 매핑이 적혀 있는 패턴. 피싱 공격의 표적 선정에 사용됩니다.
「CLAUDE.md는 개인의 로컬 설정이니까, 리포지토리(Repository)에 커밋할 필요는 없다」라고 저도 처음에는 생각했습니다.
하지만 현실에서는 다음과 같은 흐름으로 커밋되어 버립니다.
- 개인이
git add .로 모든 파일을 스테이징(Staging)해 버림 .gitignore에 CLAUDE.md가 들어있지 않아 그대로 통과- PR(Pull Request) 시 리뷰어도 「컨텍스트 파일이니까 친절하네」라고 생각하며 approve(승인)
- main에 머지(Merge)되고,
git push로 전 세계에 공개
특히 문제가 되는 것은, 팀에서 Claude Code를 공유하고 있는 케이스입니다. 「CLAUDE.md를 팀에서 공유하고 싶다」는 동기 자체는 옳습니다. 하지만 공유 대상이 public 리포지토리라면, 그 순간 사내 지식(Knowledge)이 전부 공개됩니다.
private 리포지토리라도 퇴직자가 fork하여 외부로 복사할 리스크는 남아 있습니다. CLAUDE.md의 본질은 「Claude에게 전달할 컨텍스트(Context)」이지, 「Git으로 관리해야 할 코드」가 아닙니다.
제가 현시점에서 .gitignore에 추가할 것을 권장하는 패턴을 적어둡니다. 프로젝트 템플릿에 직접 복사해서 사용하세요.
# === AI assistant context files ===
# Claude Code
CLAUDE.md
...
팀에서 공유하고 싶은 경우에는 다음과 같은 2층 구조로 구성하는 것을 권장합니다.
project/
├── CLAUDE.md # ← .gitignore로 제외, 개인의 로컬 설정
├── CLAUDE.shared.md # ← Git으로 관리, 공개해도 문제없는 범용 컨텍스트
...
CLAUDE.shared.md에는 「코딩 규약」, 「테스트 작성법」, 「PR 규약」 등의 일반적인 규칙만 적습니다. 사내 URL, 고객명, 미발표 제품명은 절대로 적지 마세요. 이것을 철저히 지키면 공유와 보안을 모두 양립할 수 있습니다.
저는 CLAUDE.shared.md에 적은 내용을 Claude Code에 @CLAUDE.shared.md로 매번 참조하게 하고 있습니다. 글로벌 CLAUDE.md (~/.claude/CLAUDE.md)에는 개인의 작업 스타일, 프로젝트 CLAUDE.md에는 사내 정보, CLAUDE.shared.md에는 공개 가능한 규칙, 이라는 3층 분리 방식입니다.
여기서부터가 본론입니다. .gitignore에 추가하는 것만으로는, 과거의 커밋 히스토리(Commit History)에 남은 CLAUDE.md는 사라지지 않습니다.
git rm --cached CLAUDE.md를 하여 커밋하더라도, git log를 따라가면 누구나 예전 내용을 읽을 수 있습니다. GitHub 페이지에서는 보이지 않더라도, git fetch --all을 하면 가져올 수 있습니다.
히스토리 자체를 지우려면 다음과 같은 절차가 필요합니다.
# git-filter-repo를 설치 (pip 또는 brew)
pip install git-filter-repo
# 리포지토리를 일단 클론 (--mirror로 모든 ref를 가져옴)
...
여러 파일을 한꺼번에 지우려면 --path를 나열하여 지정합니다.
git filter-repo \
--invert-paths \
--path CLAUDE.md \
...
filter-repo가 도저히 작동하지 않는 환경에서는 BFG Repo-Cleaner (rtyley.github.io/bfg-repo-cleaner)를 사용합니다.
# java가 필요함
java -jar bfg.jar --delete-files CLAUDE.md your-repo.git
cd your-repo.git
...
force push를 하더라도, GitHub은 커밋 SHA (Commit SHA)를 한동안 캐시합니다. 검색 엔진의 캐시도 남습니다.
따라서 GitHub Support에 「Sensitive Data Removal」 요청을 보냅니다.
요청처: https://support.github.com/contact/private-information
작성 내용은 다음 템플릿으로 충분합니다.
Subject: Request to purge cached commits
Repository: github.com/your-org/your-repo
Commit SHAs containing sensitive data:
...
보통 24~72시간 이내에 대응해 줍니다.
유출된 인증 정보 자체는 별도로 로테이션(Rotation) 하세요. git 히스토리에서 지우더라도, 과거에 클론(Clone)한 제삼자의 로컬에는 남아 있습니다. API 키, 내부 URL, IAM Role은 「유출되었다」는 전제로 취급하는 것이 안전한 판단입니다.
force push 이후에는, 이미 클론하고 있는 모든 멤버가 기존의 로컬 리포지토리(Local Repository)를 버리고 다시 클론(Re-clone)해야 합니다. 이를 공지하지 않으면, 누군가가 오래된 히스토리를 다시 푸시(Push)하여 상황을 망쳐놓을 수 있습니다.
Slack 등으로 공지 문구를 올려둡시다.
@channel
보안 대응을 위해 리포지토리의 히스토리를 재작성했습니다.
다음 작업을 실행해 주세요.
...
사람은 잊어버릴 수 있다는 전제하에, CI에서 차단하는 메커니즘을 넣어둡니다. pre-commit hook + GitHub Actions의 2단계 방어 체계를 추천합니다.
.git/hooks/pre-commit
(또는 pre-commit 프레임워크 설정)에 다음을 추가합니다.
#!/bin/sh
BLOCKED_FILES="CLAUDE.md|\ .cursorrules|AGENTS.md|MEMORY.md"
if git diff --cached --name-only | grep -E "^($BLOCKED_FILES)$" > /dev/null; then
...
# .github/workflows/block-ai-context.yml
name: Block AI context files
on: [pull_request]
...
pre-commit hook은 개인이 비활성화할 수 있으므로, 반드시 서버 측 체크를 병행해야 합니다.
엔지니어의 「커밋해서는 안 되는 목록」은 AI 네이티브 개발의 도래와 함께 확실히 늘어났습니다. 10년 전에는 .env와 비밀키만 주의하면 됐지만, 지금은 AI 컨텍스트 (AI Context) 전반이 그 목록에 추가되었습니다.
CLAUDE.md, .cursorrules, AGENTS.md, MEMORY.md. 이것들은 편리하기 때문에 사내 지식(Internal Knowledge)이 집약되기 쉽고, 그대로 공개되면 최악의 유출원이 됩니다.
작성 내용과 공개 범위라는 두 가지 측면에서 생각하세요. 작성 내용은 편의성을 우선하여 써도 좋습니다. 하지만 공개 범위는 .gitignore로 엄격하게 제어해야 합니다. 이것만으로도 다음 주 월요일 아침, Slack을 보며 얼굴이 창백해질 확률은 극적으로 낮아집니다.
지식을 축적하는 메커니즘은 유출을 방지하는 메커니즘과 세트로 갖춰져야 비로소 기능합니다.
자세한 Claude Code 운용 노하우는 Claude Code 완전 가이드에도 정리해 두었습니다. CLAUDE.md의 내용 설계, 글로벌/프로젝트/공유의 3층 분리, 팀 운용 패턴을 실례와 함께 작성했습니다.
- CLAUDE.md는 「당신의 프롬프트 그 자체」입니다. 작성 내용은 점점 사내 지식에 가까워집니다.
- GitHub Search에서
path:CLAUDE.md만 검색해도 5만 건 이상이 나오며, 그중 상당수가 사내 정보를 포함하고 있습니다. .gitignore
에 CLAUDE.md, AGENTS.md, .cursorrules, .windsurfrules, MEMORY.md 등을 한꺼번에 추가하세요 - 공유하고 싶은 규칙은 CLAUDE.shared.md로 분리하세요 - 이미 커밋해 버린 경우에는 git filter-repo로 히스토리에서 제거 → force push → GitHub Support에 캐시 무효화를 요청하세요 - 인증 정보는 히스토리를 삭제하더라도 "유출되었다"는 전제하에 로테이션(Rotation)하세요
- pre-commit hook과 GitHub Actions의 2단계로 CI를 차단하세요
지금 바로 git ls-files | grep CLAUDE.md를 실행하여, 결과가 나온다면 즉시 조치하세요.
재미있게 가봅시다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기