포스트

왜 커밋에 전자 서명을 하는가?

깃허브에서는 전자 서명된 커밋에 verified 뱃지를 부여합니다.

이 전자 서명은 꽤 중요하고 필수적입니다. 규모있는 모든 오픈소스 프로젝트에서는 커밋에 전자 서명할 것을 요구합니다.

Git은 GitHub가 아니다.

GitHub가 오픈소스 프로젝트와 Git 호스트 서비스의 상징과도 같게 되면서, 종종 Git과 GitHub가 서로 다른 것이라는 사실이 가려지는 듯 합니다.

최근의 GitHub는 다양한 기능과 서비스를 제공하고 있지만, 여전히 Git이 관리할 수 있는 Git 리포지토리를 원격지에 저장하고 Git 서버를 호스팅하는 것이 핵심이라는 것은 변하지 않습니다.

따라서 GitHub에 공개된 리포지토리는 GitLab, BitBucket과 같은 다른 Git 호스팅 서비스에도 업로드할 수 있고 심지어는 셀프 호스트 Git 서버로도 동작할 수 있습니다.

다시 말해 커밋을 생성하는 것에는 GitHub 계정이 필요하지 않습니다. GitLab은 GitHub이 관리하는 계정 데이터에 엑세스할 수 없지만 GitHub의 리포지토리를 그대로 업로드하더라도 커밋 기록은 손상되지 않습니다.

커밋 작성자는 원격지에 푸시한 사람과 동일인이 아닐 수 있다

사실 GitHub에서 관리되는 리포지토리가 다른 Git 서버와 호환성을 갖는 것은 자명한 사실입니다.

하지만 이것을 이용하면 해커는 리포지토리나 커밋을 위변조하여 공격할 수 있습니다. 공급망 공격으로 일컫는 것이 일반적인 유형입니다.

GitHub에 커밋을 푸시하기 위해서는 GitHub 계정이 필요하므로, 사람들은 GitHub에 푸시된 커밋의 작성자를 커밋을 푸시한 계정의 사용자와 동일시하는 경향이 있습니다.

하지만 이러한 생각은 위험합니다. 커밋의 작성자와 푸시한 사람은 서로 다를 수 있습니다.

GitHub 계정의 핸들이나 표시 이름 도중에 변경한다고 하더라도 변경 이전의 커밋 작성자 이름까지 함께 변경되지 않습니다. 로컬 머신의 user.nameuser.email 설정을 GitHub 계정의 것과 다르게 설정하고 푸시하면 로컬 머신의 설정대로 생성된 커밋이 그대로 서버에 업로드됩니다.


위 커밋은 이전에 사용한 명의Park, Jonghyeon로 생성되었고, 지금의 명의Jonghyeon Park와 다릅니다. 이메일 주소도 현재의 것과 다르기 때문에 프로필 사진도 GitHub의 기본 Placeholder로 표현됩니다.

다시 말해 커밋의 작성자와 GitHub 계정의 두 명의는 서로 동일함을 보장하지 않으며, 연동되지 않습니다.

GitHub 계정만으로는 커밋 저자의 신원을 보장할 수 없다

커밋의 작성자와 GitHub 계정의 동일성을 보장할 수 없는 것은 잠재적으로 문제가 됩니다. 위에서 암시했던 바와 같이, BitBucket과 같은 GitHub 바깥의 Git 서비스에 리포지토리를 옮기는 것이 아니라고 하더라도 그렇습니다.

상당한 비약이지만, 어떠한 수단으로든 공격자가 로컬 머신에 접근하고 중간에 임의의 커밋을 섞어 함께 푸시되도록 한다면, 커밋의 작성자가 아닌 이상 악의가 섞인 커밋을 확인해내는 것은 매우 어렵습니다.

위의 우려는 사실 매우 이례적인 상황에 대한 기우일지도 모릅니다.

하지만 커밋에 전자 서명하는 것은 지금 널리 사용되고 있는 Git 시스템의 약점을 보완하고, 일련의 극적인 상황에서 외부의 공격을 선제적으로 막을 수 있는 조치입니다.

덧붙임

혹자는 커밋에 전자 서명을 하는 것이 GitHub 계정이 해킹당했을 때의 피해를 막거나 줄이기 위함이라고 주장합니다. 동의할 수 없습니다. 전자 서명은 계정에 해킹당했을 때의 피해를 막을 수 없습니다. 오히려 공격자는 피해 계정에 본인이 임의로 생성한 전자 서명 키를 등록하여 무력화할 수 있습니다.* 그 어떤 상황에서도 임의의 제 3자가 계정에 접근할 수 있어서는 안됩니다.

* 물론 이 경우 공격자가 등록한 키를 이용하여, 해당하는 키로 서명된 커밋을 쉽게 식별하고 신뢰하지 않도록 할 수 있습니다.

어떤 문서에 대해 서명을 하면 그 문서의 내용에 따라 서명자는 일련의 책임을 갖게 되기 마련입니다. 많은 사용자들이 소스코드를 손댈 수 있도록 설계된 Git 시스템에서, 그것도 오픈소스 소프트웨어 개발의 상징과도 같은 시스템에서, 자신의 소스코드에 서명을 한다는 것은 서명한 것에 대해서는 자신이 책임을 지겠다는 것을 표현한 행위라고 생각합니다.