개발자들이 매일 사용하는 버전 관리 시스템 Git에서 예상치 못한 보안 취약점이 발견되었습니다. 바로 '인자 주입(argument injection)' 공격인데, 이는 신뢰할 수 없는 입력이 Git 명령의 옵션으로 해석되면서 발생합니다. 일반적인 유닉스(Unix) 도구와 달리 Git의 `--`는 옵션 해석의 끝이 아닌, 리비전(revision)과 경로 명세(pathspec)를 구분하는 역할을 해왔기 때문에, 리비전 위치에 옵션 종료 표식이 없어 문제가 발생할 수 있었습니다.
이러한 문제를 해결하기 위해 Git 2.24.0 버전부터 `--end-of-options`라는 새로운 옵션이 도입되었습니다. 이 옵션은 Git 명령에서 옵션과 리비전 사이를 명확히 구분하여, 대시(-)로 시작하는 리비전 이름이 옵션으로 오해되는 것을 방지합니다. 예를 들어, `git log --end-of-options "$rev" -- "$path"`와 같이 사용하면, 첫 번째 `--end-of-options`는 옵션과 리비전을, 두 번째 `--`는 리비전과 경로를 구분하여 안전하게 명령을 실행할 수 있습니다. 하지만 문제는 대부분의 패키지 관리자(예: Bundler, npm, pip 등)가 Git 바이너리를 실행하면서도 이 `--end-of-options`를 사용하지 않고 있다는 점입니다. 조사된 19개 패키지 관리자 중 Go의 `cmd/go`만이 이 옵션을 사용하고 있었으며, 이는 `CWE-88` 인자 주입 취약점으로 이어질 수 있습니다.
이러한 인자 주입 취약점은 셸(shell)을 거치지 않고 `argv` 배열을 직접 사용하는 경우에도 발생할 수 있습니다. 과거 Git, Mercurial, SSH 등 여러 버전 관리 시스템에서 유사한 취약점이 반복적으로 발견되었으며, 이는 URL의 호스트명이 SSH 옵션으로 처리되거나, `git fetch` 명령에서 참조(ref)가 `--upload-pack`과 같은 옵션으로 해석되는 방식으로 악용될 수 있었습니다. 패키지 관리자들이 Git URL이나 참조를 하위 프로세스에 전달하는 과정에서 이러한 취약점이 발생할 가능성이 높습니다.
문제 해결이 더딘 주된 이유는 오래된 Git 버전과의 호환성 때문입니다. `--end-of-options`는 서브명령마다 지원 시점이 다르며, `git checkout`이나 `git reset` 같은 일부 명령은 Git 2.43.1에 이르러서야 완전히 지원됩니다. 따라서 패키지 관리자들이 이 옵션을 사용하려면 최소 Git 버전을 높여야 하는데, 이는 우분투(Ubuntu) 18.04처럼 오래된 Git 버전을 사용하는 사용자들을 지원할 수 없게 만드는 결과를 초래합니다. 이러한 호환성 제약 때문에 많은 패키지 관리자는 여전히 대시로 시작하는 브랜치명을 거부하는 등의 부분적인 방어책에 머물러 있습니다.
장기적인 해결책으로는 Git 바이너리를 직접 실행하는 대신 `libgit2`, `gitoxide`와 같은 Git 라이브러리를 사용하는 방법이 제시됩니다. 라이브러리는 별도의 `argv` 경계가 없어 인자 주입 공격의 대상 자체가 사라지기 때문입니다. 하지만 이 경우 Git 업스트림(upstream)의 모든 체크아웃 안전성 수정 사항을 직접 추적해야 하는 추가적인 개발 및 유지보수 비용이 발생합니다. 결국, 개발 생태계 전반의 보안 강화를 위해서는 Git 사용 방식에 대한 근본적인 이해와 함께, 최신 보안 기능을 적극적으로 도입하려는 노력이 필요합니다.