docker-credential-acr-env 헬퍼는 레지스트리 호스트명이 ACR(Azure Container Registry)인지 판별할 때 앵커(anchoring) 없이 .azurecr.io 문자열의 포함 여부만 검사하고, 이 판별을 통과한 호스트의 oauth2/exchange 엔드포인트로 Azure AD(AAD) 액세스 토큰을 담은 POST 요청을 전송합니다. 그래서 evil.azurecr.io.attacker.com처럼 이름 중간에 .azurecr.io를 품은 공격자 통제 호스트도 유효한 ACR 레지스트리로 분류되고, AAD 액세스 토큰이 공격자 쪽 호스트로 넘어가는 구조입니다. 이 문제는 Go 취약점 데이터베이스에 GO-2026-6225로 등록돼 있습니다.
docker-credential-acr-env는 ACR을 쓰는 환경에서 자격증명을 대신 공급하는 credential helper입니다. 본 글은 2026-11-06 기준 확보된 근거만으로 작성했으며, 근거로 확인되지 않은 사항은 마지막 섹션에서 별도로 구분해 다룹니다.
docker-credential-acr-env와 앵커 없는 ACR 호스트 검증 결함
헬퍼의 역할과 결함이 중요한 이유
ACR 인증은 컨테이너 빌드·배포 자동화에서 등장하는 구성입니다. 예컨대 Docker가 공식적으로 유지보수하는 재사용 가능 GitHub Actions 워크플로 문서도 레지스트리 인증 대상의 하나로 Azure Container Registry를 나열합니다. 이런 환경에서 자격증명 공급을 대신 맡는 구성 요소가 바로 docker-credential-acr-env입니다. 자격증명 공급자의 호스트 판별 로직이 잘못되면 인증 절차 자체가 토큰의 유출 경로로 변합니다. 이번 docker-credential-acr-env 취약점 논의는 여기서 출발합니다.
앵커 없는 문자열 포함 검사가 만드는 판별 오류
헬퍼는 레지스트리 호스트명이 ACR인지 판별할 때 앵커 없이 .azurecr.io 문자열의 포함 여부만 검사하는 패턴을 사용합니다. 앵커는 해당 문자열이 호스트명의 특정 위치에 고정돼 일치해야 한다는 조건을 뜻하는데, 이 조건이 없으면 .azurecr.io가 이름 어느 위치에 나타나도 검사를 통과합니다. 실제로 evil.azurecr.io.attacker.com과 같이 이름 중간에 .azurecr.io를 포함한 공격자 통제 호스트가 유효한 ACR 레지스트리로 분류되는 것이 확인됐습니다.
공격 경로: 문자열 포함 검사를 통과한 호스트로 가는 oauth2/exchange 토큰 전송
확인된 전송 흐름
확인된 메커니즘은 다음 순서입니다.
- 헬퍼가 레지스트리 호스트명을 앵커 없이
.azurecr.io포함 여부만 검사합니다. - 검사를 통과한 호스트명은 토큰 교환(exchange) 클라이언트 구성에 그대로 사용됩니다.
- 헬퍼는 그 호스트의
oauth2/exchange엔드포인트로 POST 요청을 보내며 AAD 액세스 토큰을 전송합니다. - Go 취약점 데이터베이스 GO-2026-6225는 헬퍼의 Get 동작이 공격자 통제 호스트로 AAD 액세스 토큰을 보낸다고 기록했습니다.
유출 성립 조건 가운데 확인되지 않은 부분
메커니즘이 존재하는 것과 유출이 항상 성립하는 것은 다른 이야기입니다. 그 호스트로 가는 이름 해석 경로, TLS 인증서 처리 방식, 그리고 받는 서버가 요청자를 검증하는지 여부는 이번에 확보된 두 출처에서 확인되지 않았습니다. 이 세 가지는 실제 악용 가능성을 가늠할 때 반드시 짚어야 하는 미확인 변수입니다.
GO-2026-6225와 업스트림 이슈 #21이 교차 확인한 것과 확인하지 않은 것
Go 취약점 데이터베이스는 이 문제를 GO-2026-6225로 등록했습니다. 앵커 없는 호스트 검사와 공격자 호스트로의 토큰 전송이라는 핵심 메커니즘은 업스트림 이슈 #21과 GO-2026-6225가 겹쳐 확인한 지점입니다. 확인된 사실과 확인되지 않은 사실의 경계는 다음 표와 같습니다.
| 구분 | 항목 | 근거 |
|---|---|---|
| 확인됨 | 호스트명 판별 시 앵커 없이.azurecr.io 문자열 포함 여부만 검사 | |
| 확인됨 | 통과한 호스트명을 토큰 교환 클라이언트 구성에 그대로 사용 | |
| 확인됨 | 해당 호스트의 oauth2/exchange 엔드포인트로 AAD 액세스 토큰을 담아 POST 전송 | |
| 확인됨 | Go 취약점 데이터베이스 GO-2026-6225 등록 및 Get 동작 기록 | |
| 확인 안 됨 | 공격자 호스트로 가는 이름 해석(DNS) 경로 | |
| 확인 안 됨 | TLS 인증서 처리 방식 | |
| 확인 안 됨 | 수신 서버가 요청자를 검증하는지 여부 |
영향 범위: 유출 대상은 AAD 액세스 토큰이다
유출 대상은 AAD 액세스 토큰입니다. 리포트의 정리에 따르면 노출 범위는 그 토큰이 실제로 가진 권한을 넘지 않습니다. 토큰이 특정 레지스트리 접근용이면 노출은 해당 레지스트리에 집중되고, 더 넓은 권한을 담고 있으면 다른 Azure 자원으로 확장될 수 있습니다. 임의의 외부 호스트로 나가는 요청이 차단된 환경에서는 메커니즘이 존재해도 유출이 실행되지 않습니다. 이 정리는 토큰 권한과 이그레스 통제라는 두 변수를 점검 우선순위로 끌어올립니다. 다만 각 환경의 실제 토큰 권한과 네트워크 정책은 조직이 직접 확인할 몫입니다.
탐지 관찰점: oauth2/exchange POST 요청 로그와 아웃바운드 트래픽
공식 탐지 지침은 이번 근거에서 확인되지 않았고, 리포트는 메커니즘에서 도출한 조건부 관찰점 두 가지를 제시했습니다.
.azurecr.io를 포함하면서도 실제 ACR 호스트 형식이 아닌 이름을 향해 나간oauth2/exchangePOST 요청 흔적 확인- 헬퍼가 놓인 환경에서 예상치 못한 외부 호스트 연결에 대한 아웃바운드 모니터링
실제로 어떤 로그와 네트워크 흐름이 남는지는 이번에 확보된 근거로는 확인되지 않았습니다. 관찰점을 탐지 규칙으로 구체화하기 전에 자기 환경의 로그 원천에서 해당 패턴이 관찰되는지 먼저 검증하는 것이 순서입니다.
대응 순서: 헬퍼 사용 확인, 이그레스 제한, 대체 자격증명 방식
리포트의 대응 목록은 버전 정보와 공식 패치 안내가 없는 현 단계에서 메커니즘에서 도출한 조건부 권고이며, 공식 지침을 대체하지 않는다는 전제입니다.
- docker-credential-acr-env 헬퍼 사용 여부 확인
- 레지스트리 호스트명과 credential helper 구성 점검
- 이그레스 제한 검토
- 앵커된 검증이 적용된 수정 버전으로 업그레이드(수정 버전 번호는 미확정)
- 헬퍼 중단 후 대체 자격증명 방식 전환
- 허용된 ACR 호스트로 제한하는 네트워크 정책 유지
대체 자격증명 방식으로 전환할 때는 도구별 호환성도 함께 따질 문제입니다. 예컨대 Apptainer 1.3 공식 사용 문서는 외부 Docker credential helper의 자격증명은 읽을 수 없고 ~/.docker/config.json에 직접 저장된 정보만 읽는다고 명시합니다. 저장 방식을 바꾸면 그 자격증명을 읽어 가는 도구의 동작도 달라집니다. 이 점은 전환 계획에 반영할 부분입니다.
확인되지 않은 사항: 버전 번호, CVE 매핑, KEV, 악용 사례, PoC
이번 근거 장부에서 확인되지 않은 사항은 다음과 같습니다. 확인되기 전까지는 사실로 단정할 수 없는 영역입니다.
- 정확한 취약 버전과 수정 버전 번호
- CVE 번호와의 공식 매핑
- 벤더(예: Microsoft) 권고문
- CISA KEV 등재 여부
- 실제 악용 사례
- 공개 PoC 존재 여부
oauth2/exchange요청에서 토큰이 담기는 위치(헤더, 본문 등)- 유출 의심 상황의 토큰 처리와 관련 계정 점검에 대한 공식 지침
- 업스트림 이슈 #21과 GO-2026-6225 원문(URL은 리포트 참고자료로 존재하나 본문 직접 수집은 이뤄지지 않음)
- CI/CD 등 자동화 환경 특유의 노출 양상과 탐지 난이도
지금까지 확인된 결론은 명확합니다. docker-credential-acr-env 취약점의 핵심은 앵커 없는 문자열 검사가 공격자 통제 호스트를 ACR로 통과시키고, 통과한 호스트의 oauth2/exchange 엔드포인트로 AAD 액세스 토큰이 전송된다는 구조입니다. 나머지 조건의 사실 확인과 대응 수위 결정은 각 환경에서 확보하는 근거 위에서 이뤄집니다.