Gitea Private Container Registry 인증 우회 취약점(CVE-2026-27771)
자체 호스팅 Git 서비스를 제공하는 Gitea 는 코드 저장소의 버전 관리뿐만 아니라 Docker 컨테이너 이미지와 패키지를 관리하는 레지스트리 기능도 제공한다. 최근 발견된 CVE-2026-27771 취약점은 Gitea의 이러한 컨테이너 레지스트리 관리 서비스를 공격해 비인가된 사용자가 컨테이너 이미지를 마음대로 읽게 만든다. 해당 취약점은 1.26.2 미만의 모든 Gitea 버전이 영향을 받으므로 신속한 업데이트, 설정 관리가 필요하다.
1. 취약점 분석
Gitea의 패키지 레지스트리에 등록한 컨테이너 이미지는 Git 저장소가 아니라 사용자 또는 조직(owner)에 귀속된다. 패키지를 특정 저장소에 연결하는 기능도 저장소 화면에 패키지를 표시하기 위한 연결일 뿐, 저장소의 공개 범위를 패키지에 상속하지 않는다. 따라서 공개 사용자·조직이 소유한 패키지는 비공개 Git 저장소에 연결되어 있더라도 공개 패키지로 처리된다. 문제는 1.26.1 이하 버전의 화면이 패키지의 실제 공개 범위를 표시하지 않았고, 연결 설정에도 이 동작을 설명하지 않아 운영자가 비공개 저장소에 연결된 이미지를 비공개 레지스트리로 오인하기 쉬웠다는 점이다.
기본값인 REQUIRE_SIGNIN_VIEW=false 환경에서 비로그인 사용자가 컨테이너 레지스트리에 접근하면 Gitea는 내부적으로 UserID=-1인 Ghost 사용자를 사용해 OCI 레지스트리용 Bearer 토큰을 발급한다.

이후 패키지 접근 권한을 계산하는 determineAccessMode()는 요청자가 Ghost 사용자이더라도 패키지 소유자의 공개 범위가 public이면 읽기 권한을 부여한다.

이 때문에 공격자는 계정이나 비밀번호 없이도 일반적인 Docker/OCI API 요청만으로 이미지의 태그, 매니페스트, 설정 파일과 레이어를 내려받을 수 있었다.

패치된 버전의 코드에서는 사용자가 실제로 해당 저장소에 대한 접근 권한이 있는 지 확인하는 조건문이 추가되었다.

다만 이 취약점이 1.26.2 미만의 모든 서버에서 곧바로 모든 이미지를 노출한다는 뜻은 아니다. 실제 노출에는 다음 조건이 필요하다.
- Gitea의 내장 컨테이너 레지스트리를 사용한다.
- 패키지 소유자인 사용자 또는 조직의 공개 범위가
public이다. [service].REQUIRE_SIGNIN_VIEW가 기본값인false로 설정되어 익명 접근이 허용된다.- 운영자가 비공개 저장소와의 연결을 패키지의 접근 제어로 오인했다.
소유자의 공개 범위가 limited 또는 private이면 익명 사용자는 읽기 권한을 얻지 못하며, 이 문제만으로 이미지 업로드·수정·삭제 권한이나 연결된 비공개 Git 저장소의 접근 권한까지 획득하는 것도 아니다. 그러나 컨테이너 레이어에는 애플리케이션 코드, 빌드 산출물, 환경 설정과 하드코딩된 인증 정보가 포함될 수 있으므로 기밀성 침해의 영향은 크다.
Gitea 1.26.2의 수정은 모든 컨테이너 다운로드에 인증을 강제하는 방식이 아니다. 패키지 화면에 Private 또는 Internal 표시를 추가하고, 패키지 공개 범위는 소유자로부터 상속되며 연결된 저장소가 이를 변경하지 않는다는 안내를 명시해 잘못된 보안 기대를 바로잡았다. 또한 Composer 패키지가 연결된 비공개 저장소의 소스 URL을 응답할 때 저장소 접근 권한을 확인하도록 보완했다. 따라서 업데이트 후에도 공개 소유자의 컨테이너 이미지는 의도대로 익명 다운로드가 가능하며, 비공개 운영이 필요하면 소유자의 공개 범위를 변경하거나 전역 로그인 요구 설정을 적용해야 한다.
2. 진단 & 해결법
운영 중인 Gitea 가 취약한지 확인하고자 하면 POC 스크립트를 사용해보자. 타인의 서버를 대상으로 스캐닝하는 것은 범죄 행위로 처벌받을 수 있으니 절대로 해선 안된다. 또한 종종 공격자들이 PoC 로 위장한 악성 파일을 유포하기도 하므로 PoC 스크립트를 사용하기 전에 안전 여부를 확인해야 한다.
# Scan a vulnerable instance
python3 CVE-2026-27771-exploit.py scan https://gitea.example.com
2026-05-20일, Gitea 개발자는 해당 취약점을 해결한 1.26.2 버전을 발표 했다. 근본적인 문제 해결 방법은 취약점이 패치된 1.26.2 이상의 버전으로 업데이트하는 것이다.
필자는 Docker 를 통해 운영 중이라 동일한 docker-compose 설정에 이미지 버전만 수정해 새로 컨테이너를 생성했다.
다음은 Gitea 공식 문서에서 제공하는 rootless 이미지의 docker-compose 설정이다. 본인 환경에 맞게 적절하게 값을 설정해서 사용하자.
version: "2"
services:
server:
image: docker.gitea.com/gitea:1.26-rootless
restart: always
volumes:
- ./data:/var/lib/gitea
- ./config:/etc/gitea
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "2222:2222"
업데이트 후 저장소 데이터를 읽을 수 없다면 필자가 이전에 작성한 "Gitea 업데이트 후 저장소 데이터 읽기 실패 해결법" 글을 참고하자.
만약 당장 서버를 업데이트하기 어려운 상황이면 Gitea 설정을 저장하는 app.ini 파일의 [service] 섹션에 다음과 같이 REQUIRE_SIGNIN_VIEW Key 값을 true 로 설정해 전역 인증을 강제하여 비인가 사용자의 접근을 제한할 수 있다.
[service]
REQUIRE_SIGNIN_VIEW=true