Claude Code 세션 링크가 내 공개 저장소에 남아 있었다 (정리·차단 방법)
Claude Code를 웹(claude.ai/code)이나 원격 제어(Remote Control)로 쓰다가, 제 공개 GitHub 저장소 커밋 기록에 Claude 세션 링크가 잔뜩 남아 있는 걸 발견했습니다. 정리하고 막은 과정을 적어 둡니다. 비슷한 시기에 나온 settings.local.json 비밀번호 유출 조사도 같이 정리했습니다.
1. 무슨 일인가
Claude Code를 클라우드 세션이나 원격 제어 세션으로 쓰면 커밋 메시지 끝에 이런 줄이 붙습니다.
Claude-Session: https://claude.ai/code/session_xxxxxxxxxxxx
PR 본문에도 같은 세션 링크가 들어갑니다. 따로 끄지 않으면 기본으로 붙고, 저는 공개 저장소에 올린 뒤에야 알았습니다. 확인해 보니 공개 저장소 7개의 기록에 이 링크가 남아 있었습니다.
이미 꽤 알려진 문제입니다. Claude Code 공식 저장소에 "세션 링크를 기본으로 붙이지 말아 달라"는 이슈(#66504)가 올라와 공감 100개가 넘게 달렸고, 기존 attribution 설정을 꺼도 링크는 계속 붙는다는 버그 보고(#41873, #77830)도 있었습니다. 그 결과 링크만 따로 끄는 설정 attribution.sessionUrl이 생겼습니다.
2. 왜 문제인가
- 세션은 기본이 비공개라 링크만으로 대화 내용이 보이지는 않습니다.
- 하지만 세션 ID가 공개 기록에 영구히 남고, 검색으로 찾을 수 있습니다.
- 나중에 그 세션의 공유를 켜면, 링크를 아는 사람(claude.ai에 로그인한 사람)은 대화를 볼 수 있습니다. 대화에는 작업 경로, 계정 이야기, 설정 내용 같은 게 들어가기 쉽습니다.
그래서 공개 저장소에는 넣지 않는 게 맞다고 판단했습니다. 반면 Co-Authored-By: Claude와 "Generated with Claude Code"는 AI를 썼다는 표시일 뿐이라 그대로 두기로 했습니다.
3. 내 저장소에 있는지 확인
저장소를 전부 받아(bare clone) 기록 전체를 검색합니다.
git log --all --oneline --grep='claude.ai/code'
하나라도 나오면 기록에 남아 있는 겁니다. 김에 커밋 작성자 메일도 확인해 보세요. 개인 메일이 들어가 있다면 같이 정리하는 게 좋습니다.
git log --all --format='%ae%n%ce' | sort -u
4. 앞으로 막기 (내 PC)
~/.claude/settings.json에 다음을 넣습니다.
{
"attribution": { "sessionUrl": false }
}
이것만 끄면 Co-Authored-By와 "Generated with" 표시는 그대로 남고 세션 링크만 빠집니다. 적용한 뒤에는 Claude Code가 커밋할 때 따르는 서명 안내에서 세션 링크 줄이 빠진 것을 확인했습니다.
5. 클라우드 세션은 따로 막아야 한다
여기가 제일 놓치기 쉬운 부분입니다. 클라우드 세션(claude.ai/code)은 내 PC의 ~/.claude/settings.json을 읽지 않습니다. PC에서만 막으면 클라우드에서 만든 커밋에는 계속 링크가 붙습니다.
클라우드에서 쓸 수 있는 방법은 두 가지입니다.
- 저장소 안
.claude/settings.json에 같은 설정을 넣기: 확실하지만 저장소마다 넣어야 합니다. - 클라우드 환경의 설정 스크립트에서
~/.claude/CLAUDE.md에 "커밋·PR에 세션 링크를 넣지 않는다" 규칙을 써 넣기: 저장소를 건드리지 않아도 됩니다.
저는 두 번째로 했고, 실제로 클라우드 커밋에서 빠지는지는 아직 확인 중입니다. 결과가 나오면 이 글에 덧붙이겠습니다.
6. 이미 올라간 기록 지우기
기록을 다시 쓰는 작업이라 커밋 해시가 전부 바뀝니다. 반드시 백업부터 합니다.
# 1) 백업
git clone --mirror https://github.com/USER/REPO.git backup/REPO.git
# 2) 작업 사본에서 기록 다시 쓰기
git clone --bare backup/REPO.git work/REPO.git
cd work/REPO.git
git filter-branch -f \
--msg-filter 'grep -v "claude\.ai/code" || true' \
--env-filter '
if [ "$GIT_AUTHOR_EMAIL" = "old@example.com" ]; then
GIT_AUTHOR_EMAIL=ID+USER@users.noreply.github.com; GIT_AUTHOR_NAME=USER; fi
if [ "$GIT_COMMITTER_EMAIL" = "old@example.com" ]; then
GIT_COMMITTER_EMAIL=ID+USER@users.noreply.github.com; GIT_COMMITTER_NAME=USER; fi' \
--tag-name-filter cat -- --branches --tags
# 3) 남은 게 없는지, 파일 내용(tree)은 그대로인지 검사한 뒤
git log --branches --tags --format=%B | grep -c "claude\.ai/code"
# 4) 덮어쓰기
git push --force https://github.com/USER/REPO.git \
'refs/heads/*:refs/heads/*' 'refs/tags/*:refs/tags/*'
주의할 점
- 포크한 저장소는 건드리지 않았습니다. 원래 기록이 원작자 것이라, 다시 쓰면 원본과 어긋납니다.
- 다른 사람이 이미 받아 간 사본이나 포크에는 옛 기록이 남습니다.
- GitHub에는 옛 커밋이 해시로 한동안 열릴 수 있습니다. 완전히 지우려면 GitHub 지원에 요청해야 합니다.
- 브랜치 보호 규칙이 있으면 강제 push가 막히니 잠시 풀어야 합니다.
7. 덤: "다시 묻지 않기"가 비밀번호를 올린다
보안 회사 Apiiro가 공개 GitHub에 있는 .claude/settings.local.json 104,185개를 전부 조사했더니 1,122개에 진짜 비밀번호나 키가 들어 있었다고 합니다(원문).
원리는 단순합니다. Claude Code가 DB 확인 같은 명령을 실행하려 할 때 "Yes, and don't ask again"을 누르면, 그 명령 문자열이 비밀번호까지 통째로 허용 목록에 저장됩니다. 그 파일이 커밋되면 그대로 공개됩니다. Claude Code가 파일을 만들 때 전역 git 제외 목록에 넣어 주긴 하지만, 나중에 저장소가 된 폴더나 다른 PC의 사본은 보호받지 못합니다.
확인 방법(기록 전체):
git log --all --name-only --format= | grep -E '\.claude/|settings\.local\.json|\.mcp\.json' | sort -u
저는 제 저장소 17개를 모두 검사했고 다행히 한 번도 올라간 적이 없었습니다. 나왔다면 순서는 이렇습니다.
- 들어 있던 키·비밀번호부터 새로 발급(파일을 지워도 기록·포크에는 남습니다)
git rm --cached .claude/settings.local.json하고 저장소.gitignore에 추가- 명령에 비밀번호를 직접 쓰지 말고
$DB_URL같은 환경 변수로 넘기기 - 허용은 명령 통째로가 아니라
Bash(npm run:*)같은 패턴으로
정리: 공개 저장소 점검 목록
- 기록에
claude.ai/code링크가 있는지 - 커밋 작성자 메일이 개인 메일인지
.claude/,settings.local.json,.mcp.json이 올라간 적 있는지- PC 설정
attribution.sessionUrl: false - 클라우드 세션은 별도로 막기
- 명령에 비밀번호를 직접 쓰지 않기
AI와 같이 코딩한다는 표시는 남겨도 괜찮지만, 세션 링크와 비밀번호는 공개 저장소에 남기지 않는 게 좋겠습니다.