GitLab2Shell 대응: CVE-2026-110264 버전 확인과 업그레이드
이 글의 목차
GitLab2Shell 대응은 GitLab CE/EE의 CVE-2026-110264 수정 릴리스로 업그레이드하고 실제 배포에 반영하는 작업입니다. GitLab의 10월 21일 공지는 특정 조건에서 정규식 컴파일 중 정수 오버플로로 인증 없는 원격 코드 실행이 가능했다고 설명합니다. GitLab Shell이나 Runner의 버전만 올리는 것으로 CE/EE 서버 수정이 완료되지는 않습니다.
먼저 CVE와 제품 버전을 맞추세요
이 글은 GitLab 공식 공지의 CVE-2026-110264를 다룹니다. CVSS v3.1 점수는 10.0입니다. 비슷한 시기의 다른 GitLab CVE나 다른 제품의 Shell 이름과 구분해야 합니다. GitLab이 작성한 CVE 레코드도 같은 영향 범위와 수정 기준을 기록합니다.
| GitLab CE/EE 계열 | 해당 CVE 최초 수정 릴리스 |
|---|---|
| 18.11 | 18.11.13 |
| 19.0 | 19.0.10 |
| 19.1 | 19.1.9 |
| 19.2 | 19.2.9 |
| 19.3 | 19.3.6 |
| 19.4 | 19.4.3 |
| 19.5 | 19.5.1 |
공지는 7.0부터 18.11.13 이전까지와 표의 각 계열에서 최초 수정 이전 버전을 영향 범위로 명시합니다. 표는 2026년 10월 30일에 확인한 최초 수정 기준이며 현재 설치할 최신 버전을 고정한 목록이 아닙니다. GitLab.com과 GitLab Dedicated는 공지에 별도 반영 상태가 있으므로 Self-Managed의 업그레이드 지시를 그대로 대입하지 마세요.
선언된 버전 문자열을 오프라인으로 비교하기
그림은 아래 비교 코드의 흐름입니다. 입력을 검증한 뒤 등록된 계열의 기준과 비교합니다. 더 오래된 영향 범위는 업그레이드 경로가 필요하다고 표시하고, 표 밖 계열은 미확인으로 남깁니다. 어느 결과도 서버 상태나 패치 출처를 인증하지 않습니다.
Python 3.11 이상에서 아래 파일을 새 디렉터리에 저장하세요. 정식 업스트림 CE/EE 릴리스의 숫자 기준을 비교하는 보조 도구이며 네트워크 요청·서버 탐색·취약점 악용은 하지 않습니다. 19.5.1, 19.5.1-ee, 19.5.1-ee.0 형태를 받으며, 프리릴리스·야간 빌드·공급자 커스텀 버전은 추측해서 판정하지 않습니다.
release-threshold.py
import re
import sys
FIRST_FIX = {
(18, 11): 13,
(19, 0): 10,
(19, 1): 9,
(19, 2): 9,
(19, 3): 6,
(19, 4): 3,
(19, 5): 1,
}
NUMBER = r"(0|[1-9][0-9]{0,2})"
VERSION = rf"{NUMBER}\.{NUMBER}\.{NUMBER}(?:-(?:ce|ee)(?:\.[0-9]{{1,3}})?)?"
def main(argv):
match = re.fullmatch(VERSION, argv[1]) if len(argv) == 2 else None
if match is None:
print("usage: release-threshold.py VERSION (stable CE/EE release format)", file=sys.stderr)
return 2
major, minor, patch = map(int, match.groups())
branch = (major, minor)
if branch in FIRST_FIX:
baseline = f"{major}.{minor}.{FIRST_FIX[branch]}"
state = "met" if patch >= FIRST_FIX[branch] else "below"
status = 0 if state == "met" else 1
elif (7, 0) <= branch < (18, 11):
baseline, state, status = "upgrade-path-required", "below", 1
else:
baseline, state, status = "not-covered", "outside-table", 2
print(f"release-threshold={state}")
print(f"baseline={baseline}")
print("deployment-and-release-provenance=not-verified")
return status
if __name__ == "__main__":
raise SystemExit(main(sys.argv))
python3 release-threshold.py 19.5.1-ee.0
로컬 실행에서 아래 결과와 종료 코드 0을 확인했습니다.
release-threshold=met
baseline=19.5.1
deployment-and-release-provenance=not-verified
종료 코드 0은 입력 숫자가 이 CVE의 공개 수정 기준 이상이라는 뜻입니다. 1은 공개 기준 미만, 2는 지원하지 않는 형식이나 표 밖 계열입니다. 입력한 릴리스가 실제로 존재하는지, 정식 패키지인지, 어느 노드가 실행하는지까지 확인하지 않습니다. 백포트·직접 빌드는 공급자의 패치 증거를 별도로 대조해야 합니다.
설치 버전과 실행 반영을 연결하세요
공식 유지보수 문서는 Linux 패키지 설치에서 sudo gitlab-rake gitlab:env:info, 소스 설치에서 bundle exec rake gitlab:env:info RAILS_ENV=production으로 GitLab·Ruby·구성요소 정보를 수집하는 방법을 설명합니다. 다중 노드에서는 Rails가 있는 노드에서 실행합니다. 출력에는 내부 경로·주소가 포함될 수 있으므로 제한된 운영 기록에 보관하세요.
이 명령을 운영 서버에서 실행한 것은 아닙니다. 실제 대응에서는 수집 결과를 전체 패키지 리비전·배포 이미지 digest·각 웹/백그라운드 노드와 연결하고, 업그레이드 후 모든 대상에 반영됐는지 확인해야 합니다. HTTP 배너 하나나 다른 노드의 명령 결과를 전체 배포 증거로 쓰지 마세요.
최신 패치를 고르고 마이그레이션을 완료하세요
공식 업그레이드 경로에서 현재 버전의 필수 경유 지점을 확인하고, 각 단계의 백그라운드 마이그레이션을 마친 뒤 다음 단계로 이동합니다. 오래된 설치를 표의 가장 높은 버전으로 바로 바꾸는 계획은 적절하지 않을 수 있습니다. 백업·복구 경로, 확장 기능, 작업 중단과 다중 노드 절차도 함께 정해야 합니다.
최초 수정 버전과 최신 패치는 구분하세요. 10월 29일 패치 공지에는 19.5.3·19.4.5 등 후속 버전과 일부 DB 마이그레이션이 안내되어 있으며, 19.5.2·19.4.4는 건너뛴 번호라고 명시합니다. 위 스크립트는 릴리스 목록을 조회하지 않으므로 그런 문자열도 숫자 비교만 합니다. 실제 설치 후보는 반드시 공식 배포 목록에서 선택하세요.
업그레이드 뒤에는 실행 버전·마이그레이션 완료와 정상 로그인·저장소 접근·작업 처리를 각각 확인합니다. 공식 공지의 탐지 항목인 Onigmo 워커 크래시와 Org 모드 렌더링 오류 급증은 조사 단서이며, 단독으로 침해를 확정하거나 배제하는 증거가 아닙니다. 침해 정황이 있으면 로그·프로세스·배포 증거를 보존하고 별도 사고 조사를 진행합니다.
같은 시기의 Java 인증서 대응은 별개입니다. JDK를 사용하는 빌드·통합 서비스는 eMudhra와 JVM 신뢰 저장소 확인도 함께 살펴보세요.
댓글