Git 프로젝트는 2026년 말 출시를 목표로 하는 Git 3.0에서 새로 생성되는 저장소의 기본 객체 포맷을 SHA-256으로 전면 전환할 계획이다. 이 메이저 릴리스에서는 동시에 Rust 빌드 툴체인 의무화, reftable 참조 백엔드 기본 적용, 오래된 레거시 명령어 폐기 등도 함께 추진된다. 정식 배포까지 완충 기간이 남아 있지만, 주변 도구 생태계의 호환성 검증은 지금 당장 착수해야 할 과제다.
기본값 변경 하나로 촉발되는 생태계 전체의 재검증
Git 코어 개발팀은 기존 SHA-1 포맷의 저장소도 업그레이드 후 정상적으로 작동할 것이라며 하위 호환성을 강조한다. 공식적인 설명은 호환성 파괴의 여파를 신규 프로젝트에만 한정할 수 있다는 점을 부각하려 한다. 그러나 실제 엔지니어링 현장에서 신규 저장소에만 영향을 준다는 논리는 기존 생태계의 매끄러운 진화를 거칠게 단절시키는 것과 같다. 개발자가 로컬 환경에서 테스트용 저장소를 하나 만드는 순간 구버전 IDE 플러그인은 파싱에 실패한다. 유지보수가 끊긴 배포 자동화 스크립트 역시 두 가지 포맷을 파싱하지 못해 즉각적인 오류에 직면한다.
가장 치명적인 위험은 주변 도구 생태계가 객체 해시를 40자리 16진수 문자열로 가정하고 깊숙이 의존해 왔다는 점이다. 새 저장소에서는 식별자 길이가 64자리로 단번에 늘어난다. 이 문자열 길이의 급격한 변화는 지난 15년 동안 전 세계 수많은 도구에 작성된 하드코딩 추출 규칙과 정규표현식을 단숨에 무력화한다. 지속적 통합(CI/CD) 시스템의 로그 분석 모듈은 새 포맷의 커밋 정보를 읽어 들이는 첫 단계부터 문자열 잘림이나 예외 에러를 뿜어낼 것이다.
그림: 콘텐츠 해시를 키로 사용하는 Git 키-값 객체 데이터베이스 구조도. 출처: GitButler / Butler’s Log
Git은 이미 2018년부터 SHA-256 저장소를 선택적으로 생성할 수 있도록 실험적 지원을 제공해 왔다. 보안 요구사항이 높은 프로젝트라면 스스로 마이그레이션을 선택할 수 있었다. 하지만 8년이라는 긴 시간 동안 이 무거운 전환 부담을 자발적으로 짊어진 프로젝트는 손에 꼽을 정도로 적었다. 결국 기본값을 강제로 바꾸는 것만이 생태계 전체의 전환을 실질적으로 밀어붙일 수 있는 유일한 수단이 된 셈이다.
충돌 공격과 제2 역상 공격의 결정적 차이
미국 국립표준기술연구소(NIST)는 이미 2011년에 SHA-1을 공식 폐기 권고 목록에 올렸으며, 표준화 기구의 방침은 10여 년 전부터 확고했다. 코어 개발팀이 기본값 전환을 추진하는 대외적인 명분도 명확하다. 업계 표준 기구에 의해 이미 폐기 판정을 받은 알고리즘 위에 새로운 저장소를 계속 쌓아 올려서는 안 된다는 판단이다.
반면 깃허브 공동 창업자이자 깃버틀러 창립자인 스콧 차콘(Scott Chacon) 등 반대 진영은 이 논리가 완전히 다른 차원의 보안 위협을 혼동하고 있다고 반박한다. 보안 연구진은 2017년 SHAttered 프로젝트와 2020년 Shambles 논문을 통해 구형 알고리즘에 대한 실질적인 충돌 기법을 입증한 바 있다. 그러나 정교하게 준비된 두 개의 파일이 동일한 해시값을 갖도록 만드는 것과, 원본 내용을 모르는 상태에서 기존의 정상 코드와 동일한 해시를 갖는 악성 코드를 위조해 내는 ‘제2 역상(Second-preimage) 공격’은 완전히 다른 차원의 문제다.
실제 엔지니어링 환경에서 기존 저장소를 겨냥한 제2 역상 해독 공격은 여전히 천문학적인 비용이 들며 현실적인 실행 가능성이 전무하다. 설령 Git의 무결성 검증을 이미 완전히 깨진 것으로 평가받는 MD5로 낮춘다 하더라도 사정은 크게 다르지 않다. 전 세계에 존재하는 약 30억 대의 고성능 GPU를 모조리 최신 RTX 5090으로 바꾸어 최대 연산력으로 돌린다 해도, 제2 역상을 찾아내는 데 걸리는 예상 시간은 여전히 160억 년에 달한다. 현재 인류가 보유한 하드웨어 규모로는 이론적 취약점과 실제 공격 사이의 연산력 격차를 메울 수 없다.
논문에 등장하는 충돌 공격을 실무 개발 워크플로우에서 재현하는 것 또한 현실성이 떨어진다. 공격자는 먼저 대상 저장소의 쓰기 권한을 확보한 뒤, 교묘하게 조작된 바이너리 데이터를 소스코드 커밋에 끼워 넣어야 한다. 그런 다음 상위 메인테이너를 속여 해당 브랜치를 머지하도록 유도해야 한다. 스스로 악의적 환경을 꾸민 뒤 머지를 유도하는 식의 침투 경로는 실제 사이버 범죄 생태계에서 투입 비용 대비 얻을 수 있는 대가가 거의 없다.
신뢰는 암호 해시가 아니라 가져오는 출처에서 비롯된다
이 기술적 논쟁은 버전 관리 시스템이 맡아야 할 보안의 경계가 어디인가라는 근본적인 질문으로 이어진다. 리누스 토르발스(Linus Torvalds)는 2005년 Git 탄생 당시부터 진정한 방어선은 특정 수학 공식이 아니라 배포 경로에 있다고 공개적으로 선을 그었다. 개발 환경의 보안 기준을 결정하는 핵심은 ‘어떤 신뢰할 수 있는 서버에서 코드를 풀(Pull)해 왔는가’에 있다. 이는 로컬 디스크의 원본 파일이 어떤 해시 함수를 거쳤는가보다 훨씬 결정적인 요소다.
실제 소프트웨어 공급망 침투는 수학적 해시 공격이 아니라 사회공학적 수법을 통해 이루어진다. 공격자들은 관리되지 않고 방치된 오픈소스 패키지의 관리자 권한을 돈으로 사들이는 데 훨씬 익숙하다. 또한 수개월에 걸쳐 성실한 기여자로 위장하며 프로젝트의 머지 권한을 따내기도 한다. 2024년 발생한 xz 백도어 사건이 대표적인 공급망 침투 사례다. 합법적인 코드 수정 권한을 확보해 직접 트로이목마를 심는 것이, 수십억을 들여 해시 충돌을 계산하는 것보다 비교할 수 없을 만큼 저렴하고 확실하다.
알고리즘의 비트 길이를 악의적 코드 유입을 막는 핵심 방패로 여기는 접근은 빌드 파이프라인의 실질적인 인증 사각지대를 가린다. 유효하게 서명된 릴리스 태그 아래에서 최종 배포 패키지 자체를 바꿔치기하는 공격에는 그 어떤 해시 충돌도 필요하지 않다. 오염된 데이터의 침투를 차단하는 열쇠는 배포 채널의 엄격한 검증 체계에 있으며, 해시 길이를 아무리 늘려도 이러한 운영상의 빈틈을 메울 수는 없다.
감당하기 힘든 마이그레이션 청구서: 양립할 수 없는 두 포맷의 충돌
기본값 변경에서 가장 해결하기 어려운 지점은 기존 저장소의 마이그레이션이며, 이는 백그라운드에서 조용히 처리될 수 있는 성격의 작업이 아니다.
그림: 저장소 생성 시 해시 포맷을 수동으로 선택해야 하는 호스팅 플랫폼 UI. 출처: GitButler / Butler’s Log
자체 호스팅 환경이나 프라이빗 플랫폼에서 저장소를 운영하는 개발팀은 클라이언트와 서버 양쪽의 설정을 수동으로 맞춰야 한다. 로컬 환경의 알고리즘 설정과 원격 서버의 지원 범위가 일치하지 않는 순간 푸시 작업은 즉시 가로막히며, “fatal: the receiving end does not support this repository’s hash algorithm”이라는 치명적인 오류가 발생한다.
수년간 데이터가 누적된 대규모 저장소를 변환하는 작업은 프로젝트의 전체 역사를 강제로 다시 쓰는 것을 뜻한다. 기존 SHA-1 저장소를 새 표준으로 바꾸려면 모든 blob, tree, commit 객체를 처음부터 다시 계산해 기록해야 한다. 이러한 히스토리 재작성은 과거의 커밋 노드에 부착되어 있던 모든 GPG 및 SSH 서명을 일제히 무효화한다. 또한 사내 위키나 이슈 트래커, 업무 메신저에 남아 있던 수많은 40자리 커밋 링크들은 하룻밤 사이에 모두 연결이 끊긴 데드링크로 전락한다.
Git의 서브모듈(Submodule) 구조는 생태계의 분열을 더욱 증폭시킨다. 현재 Git의 동작 규칙상 중첩된 하위 모듈은 상위 메인 저장소와 동일한 데이터 포맷을 공유해야 한다. 만약 외부에서 가져온 서브모듈이 SHA-1에 머물러 있는데 메인 저장소를 SHA-256으로 전환한다면, CI 빌드 서버는 두 가지 포맷의 의존성을 각각 별도로 미러링해 관리해야 한다. 이 이원화된 의존성 동기화가 조금이라도 삐끗하면 개발팀 전체의 자동화 빌드 파이프라인이 멈춰 서게 된다.
C 언어 기반의 공식 Git 바이너리에 의존하지 않고 독자적으로 Git 스펙을 구현한 서드파티 라이브러리(libgit2 등)의 경우 새 알고리즘 지원 속도가 현저히 느리다. 업계에서는 구글 내부에서 전사 차원의 모든 신규 프로젝트에 대해 구형 SHA-1 포맷 사용을 유지하도록 강제하는 내부 규정을 검토 중이라는 이야기까지 흘러나온다. 대형 기술 기업들이 인프라 업그레이드를 인위적으로 동결하려는 까닭은, 시니어 엔지니어들의 귀중한 자원을 호환성 오류 추적에 낭비하지 않기 위한 현실적 방어 조치다.
대안: 계산 비용을 서명 단계로 분리하는 접근법
개발팀이 새로운 표준을 추진하는 것이 즉흥적인 발상은 아니다. 전환기 동안 두 포맷을 매핑하기 위한 상호운용성 설계안은 메일링 리스트에서 수년간 심도 있게 논의되어 왔다. 인프라 설계자의 관점에서 보면, 단기적인 혼란을 감수하더라도 향후 수십 년 동안 지속될 위변조 방지 안정성을 확보하는 것이 합리적인 진화 방향이다. 기반 시스템 아키텍트는 언제나 가장 밑단의 저장 구조에서 모든 잠재적 약점을 원천 차단하려는 경향을 보인다.
반면 커뮤니티의 반대 진영은 방어 비용을 실질적으로 통제 가능한 범위 안에 묶어두는 데 초점을 맞춘다. 독립 메인테이너들은 전체 저장 계층의 포맷을 갈아엎는 대신, 커밋이나 태그 서명 객체 내부에 별도로 계산된 콘텐츠 검증 헤더(SHA-256 또는 BLAKE3)를 추가하는 대안을 제시한다. 이는 콜린 월터스(Colin Walters)가 고안한 git-evtag 도구의 방식과 유사하다.
그림: Git 객체의 서명 필드에 독립적인 콘텐츠 해시를 기록하는 구조도. 출처: GitButler / Butler’s Log
이러한 설계는 위변조 방지를 위한 연산 부담을 커밋 서명 및 검증 단계로 국소화한다. 데이터를 위조하려는 공격자는 완전히 독립적인 두 가지 암호 검증 체계를 동시에 깨뜨려야만 한다.
별도의 독립 검증 헤더를 채택할 때 얻을 수 있는 결정적 이점은 일상적인 개발 작업의 성능 부담을 완벽하게 차단한다는 데 있다. 실측 결과에 따르면 210만 개의 파일과 35GB에 달하는 Chromium 전체 저장소 트리를 대상으로 체크섬을 다시 계산하는 데 걸린 시간은 단 5초에 불과했다. 리눅스 커널의 1.5GB 코드 트리는 257밀리초, 일반적인 소규모 프로젝트는 17밀리초 만에 계산이 완료되었다. 연산 부담을 정식 릴리스 태그를 발행하는 순간으로 한정하면, 일상적으로 발생하는 수많은 커밋에 불필요한 연산 비용을 부과하지 않아도 된다.
코드베이스를 새 표준으로 강제 전환하는 대가로 얻는 것은 향후 수십 년간의 이론적 보안 여유분이다. 반면 기본값을 유지함으로써 아낄 수 있는 것은 소프트웨어 생태계 전체가 치러야 할 막대한 마이그레이션 청구서다. 양측의 전제는 분명하다. 해시 자체가 신뢰의 토대라고 믿는다면 마이그레이션은 빠를수록 좋고, 신뢰는 가져오는 출처와 배포망에서 나온다고 믿는다면 전환의 시급성은 크게 떨어진다. 메일링 리스트에서 오랜 시간 다듬어 온 포맷 간 상호운용성 매핑이야말로 이번 전환의 충격을 덜어줄 수 있는 유일한 완충 장치다.
참고 링크:
- Git 3.0 and the SHA-256 Migration
- The hidden cost of Git’s SHA-256 migration