전체 가이드
심각 심각도설정 오류

노출된 .git 디렉터리: 눈앞에 숨어 있는 소스 코드 유출

웹 서버가 애플리케이션 파일과 함께 .git 디렉터리를 제공하면, 공격자는 충분한 객체를 내려받아 전체 소스 코드를 복원할 수 있습니다. 여기에는 지금까지 커밋된 모든 시크릿이 포함되며, 이후 커밋에서 삭제한 것도 예외가 아닙니다. AppSafe는 이를 심각(critical)으로 보고합니다.

무엇인가요

Git은 전체 저장소(모든 파일, 모든 커밋, 모든 브랜치의 끝)를 프로젝트 루트의 숨김 디렉터리 .git에 저장합니다. 이 디렉터리가 웹 루트 안에 들어가고 서버가 접근을 차단하지 않으면 /.git/config, /.git/HEAD, 그리고 /.git/objects/ 아래의 객체 저장소를 누구나 내려받을 수 있습니다.

유출된 .git 디렉터리에서 전체 소스를 복원하는 것은 간단합니다. git-dumper 같은 도구는 인덱스를 가져온 뒤 참조된 모든 객체를 내려받아 완전히 동작하는 체크아웃을 만들어 냅니다. 공격자에게 셸 접근은 필요 없고 브라우저만 있으면 됩니다.

왜 중요한가요

소스 코드에는 거의 확실히 위험을 높이는 정보가 들어 있습니다. 하드코딩된 API 키(주로 오래된 커밋에), 데이터베이스 스키마, 내부 엔드포인트 경로, 비즈니스 로직, 인증 흐름 등입니다. 현재 커밋된 시크릿이 없더라도 히스토리에는 공격자가 악용할 수 있는 자료가 가득합니다.

Git 히스토리는 설계상 영구적입니다. 몇 년 전에 커밋되었다가 삭제된 시크릿도 객체 저장소에 남아 있으며 다른 모든 것과 함께 다운로드됩니다. 이를 무력화하는 유일한 방법은 교체(로테이션)입니다.

고치는 방법

nginx에서 .git 차단하기

경로가 /.git/으로 시작하는 모든 요청을 거부합니다. 디렉터리의 존재를 확인시켜 주지 않도록 403 대신 404를 반환하세요.

location ~ /\.git {
  deny all;
  return 404;
}
.git을 웹 루트 밖에 두기

가장 확실한 해결책은 처음부터 .git 디렉터리를 문서 루트에 배포하지 않는 것입니다. 빌드 결과물이 별도의 public/ 디렉터리로 출력되도록 구성하고, 프로젝트 루트가 아닌 그 디렉터리만 배포하세요.

차단되었는지 확인하기

수정 사항을 배포한 후 브라우저에서 https://yourdomain.com/.git/config를 요청해 보세요. Git 설정 내용이 아니라 404가 반환되어야 합니다. AppSafe는 매 스캔마다 이를 다시 확인합니다.

한 번이라도 커밋된 시크릿은 모두 교체하기

디렉터리에 접근할 수 있었다면, 어떤 커밋에든 나타난 모든 API 키, 비밀번호, 토큰을 유출된 것으로 간주하세요. 반드시 교체해야 합니다. 커밋을 삭제하는 것만으로는 부족합니다. 공격자가 이미 내려받았을 수 있는 pack 파일에 객체가 여전히 남아 있기 때문입니다.

자주 묻는 질문

관리형 플랫폼(Vercel, Netlify, Fly.io)에 배포하고 있습니다. 위험한가요?

소스에서 빌드하는 관리형 플랫폼은 일반적으로 빌드 결과물만 배포하므로 .git 디렉터리가 제공되지 않습니다. 위험이 더 큰 경우는 VPS 배포, 프로젝트 루트에서 빌드한 Docker 컨테이너, 작업 트리 전체가 복사되는 정적 사이트 내보내기입니다.

AppSafe는 실제로 무엇을 확인하나요?

AppSafe는 /.git/config와 /.git/HEAD를 요청하고, 응답 본문이 실제 Git 파일처럼 보이는지([core] 또는 ref: 패턴과 일치하는지) 확인합니다. Git 내용이 아닌 일반적인 200 페이지는 보고하지 않습니다.

서버의 .git 디렉터리를 그냥 삭제해도 되나요?

배포된 파일만 실행되면 된다면 그렇게 해도 됩니다. 다만 다음 푸시 때 배포 과정에서 다시 복사되지 않도록 하세요. 배포 스크립트가 일관되지 않을 때를 대비해 웹 서버 수준에서도 차단해 두면 이중 방어가 됩니다.

내 앱도 영향을 받나요?

AppSafe는 이 문제와 수십 가지 다른 문제를 한 번의 무료 스캔으로 점검합니다.

내 앱 무료 스캔