GitLab 만점 결함이 9일 만에 또 나왔다, 패치한 서버도 다시 올려야 한다
Security15분 읽기

GitLab 만점 결함이 9일 만에 또 나왔다, 패치한 서버도 다시 올려야 한다

직접 설치형 GitLab에서 로그인 없이 코드를 실행할 수 있는 만점짜리 결함이 9일 만에 또 나왔습니다. 10월 12일 패치를 마친 서버도 10월 21일 릴리스로 다시 올려야 합니다.

취약점 공지를 받으면 안내된 수정 버전으로 올리고 그 CVE 번호를 닫는 것이 보통의 순서입니다. 이번 GitLab에서는 그 순서가 9일 만에 어긋났습니다. 10월 12일에 로그인 없이 서버 코드를 실행할 수 있는 만점 결함(CVE-2026-97229)이 고쳐졌고, 19.4.2·19.3.5·19.2.8로 올린 서버가 막 안심하던 10월 21일에 같은 정규식 엔진의 또 다른 만점 결함(CVE-2026-110264, CVSS 10.0)이 고쳐졌습니다. 12일 수정판은 이 새 결함을 막지 못하므로, 직접 설치해 운영하는 GitLab CE·EE라면 12일에 올렸든 안 올렸든 21일 이후 버전이 목표입니다. 영향 범위도 12일 건(19.2 이상)보다 훨씬 넓어 7.0 이후 모든 버전이고, 공식 우회책은 없습니다. GitLab.com과 GitLab Dedicated는 GitLab이 이미 고쳐서 할 일이 없습니다. 이 글의 날짜와 시각은 모두 UTC 기준이고, 내용은 10월 27일까지 확인된 것입니다.

9월 23일부터 10월 23일까지, 릴리스 네 번

네 번의 공지가 한 달 안에 나왔습니다. 아래 그림에서 점 사이의 간격(19일, 9일, 2일)과 빨간 점 두 개를 보면 됩니다. 빨간 점이 로그인 없이 가능한 만점짜리입니다.

9월 23일 19.4.1 공지, 10월 12일 19.4.2 공지, 10월 21일 19.5.1 공지, 10월 23일 Ruby 수정판을 시간순으로 놓은 타임라인 그림 1. 같은 정규식 엔진을 다룬 릴리스 네 번(날짜는 UTC). 간격은 직전 릴리스와의 일수

9월 23일에는 한 번에 두 건이 나왔고, 12일과 21일이 각각 한 건씩 뒤를 이었으며, 23일에는 GitLab이 아니라 Ruby 쪽이 원인 버그를 고쳤습니다. 네 건 모두 해커원(HackerOne) 버그 바운티로 연구자 joaxcar가 보고했고, The Hacker News는 21일 건을 같은 연구자가 한 달 사이에 보고한 네 번째 코드 실행 결함이라고 전했습니다. 한 줄씩 대응시키면 점수가 갈린 이유까지 보입니다.

공지일 CVE 결함 종류 CVSS 로그인 Ruby에서 고친 첫 릴리스(4.0 / 3.4 / 3.3)
9월 23일 CVE-2026-89078 파서의 이중 해제 9.9 필요 4.0.0 / 3.4.12 / 3.3.13
9월 23일 CVE-2026-93577 컴파일러의 크기 계산 오버플로 9.9 필요 4.0.8 / 3.4.12 / 3.3.13
10월 12일 CVE-2026-97229 CI/CD 컴파일러의 크기 계산 오버플로(93577과 같은 원인) 10.0 불필요 4.0.8 / 3.4.12 / 3.3.13
10월 21일 CVE-2026-110264 반복이 많은 패턴에서 내부 ID 오버플로 10.0 불필요 4.0.9 / 3.4.12 / 3.3.13

9월 23일의 두 건이 9.9인 것은 공격에 낮은 권한의 계정이 필요해서이고, 12일과 21일 건은 계정이 필요 없어 10.0입니다. 9월의 두 건 이후 계정 없이 가능한 쪽으로 문턱이 낮아졌다는 점이 이 표에서 가장 눈에 띄는 변화입니다.

같은 엔진 안의 서로 다른 세 구멍

GitLab은 CI/CD 설정 파일 같은 곳에 적힌 정규식을 Ruby에 들어 있는 정규식 엔진 Onigmo로 컴파일합니다. 정규식은 문자열이 어떤 모양인지 적어 두는 짧은 패턴이고, 컴파일은 그 패턴을 엔진이 돌릴 수 있는 명령 목록으로 펼치는 일입니다. 반복 횟수가 큰 패턴은 펼치면 크기가 곱셈으로 불어나는데, 이 크기를 부호 있는 32비트 정수(최댓값 약 21억)로 계산하다가 한계를 넘으면 값이 뒤집혀 작은 수나 음수가 됩니다. 크기 검사는 “작다”고 통과시키지만 실제 펼쳐진 프로그램은 훨씬 커서, 예상한 자리를 넘어 메모리에 쓰게 됩니다. 이것이 정수 오버플로(CWE-190)이고, 메모리 손상 위에서 코드 실행이 가능해집니다.

Ruby의 10월 23일 공지는 네 건을 세 개의 서로 다른 수정으로 나눕니다.

  • Ruby 수정 #13332: 파싱이 실패했을 때 메모리를 두 번 해제하는 문제. CVE-2026-89078이 여기에 해당합니다.
  • Ruby 수정 #19020: 컴파일된 패턴의 크기를 곱셈으로 어림하는 계산의 오버플로. CVE-2026-93577과 CVE-2026-97229, 두 번호가 같은 원인입니다.
  • Ruby 수정 #16801: 반복이 많은 패턴에서 엔진 내부 식별자가 넘치는 별개의 버그. CVE-2026-110264입니다.

그러니 “같은 결함이 고쳐지지 않아서 또 나왔다”가 아닙니다. 같은 부위에서 서로 다른 계산이 따로 넘쳤습니다. 12일 수정은 크기 계산의 곱셈을 나눗셈 검사로 바꿔 넘칠 수 없게 하고 컴파일된 프로그램에 약 512MiB 상한을 둔 것으로(Rapid7 분석), 21일 건의 반복 ID 계산은 이 수정 범위 밖에 있었습니다. 문이 둘이었고 하나만 닫혀 있었던 셈입니다.

요청이 검사를 지나 컴파일러에 닿는 길

그렇다면 GitLab의 방어는 왜 이 입력을 거르지 못했을까요? 아래 그림은 입력이 GitLab 안에서 지나는 검사 층과 그 밑의 Ruby 엔진을 나란히 놓고, 수정이 들어간 자리를 초록으로 표시합니다.

CI 린트 요청과 Org 문서 렌더링이 GitLab 검사 층을 지나 Regexp.new를 거쳐 Ruby의 파서, 컴파일러 크기 계산, 반복 ID에 닿는 경로와 수정이 들어가는 자리를 그린 그래프 그림 2. 검사 층은 위에, 오버플로 계산은 아래에 있다. 수정은 엔진에 들어간다(개념도)

Rapid7이 분석한 12일 건 기준으로 GitLab은 정규식을 엔진에 넘기기 전에 여러 겹의 검사를 둡니다. 소스 길이 제한, 서브루틴 호출 금지, 반복 횟수 범위 제한, 컴파일된 크기 약 1MB 제한, 일치 검사의 50ms 제한 시간입니다. 이 검사들은 패턴의 모양을 읽습니다. 반면 Ruby는 경로 문자열이 멀티바이트(UTF-8)일 때 패턴을 다시 컴파일하고, 이 재컴파일은 크기 검사도 50ms 제한 시간도 받지 않는 구간에서 일어납니다. 모양만 읽는 검사 아래에서 엔진의 계산이 넘치면 위의 층은 아무것도 보지 못합니다.

수정이 엔진 쪽에 들어가는 방식도 두 겹입니다. GitLab은 자기 패키지(Omnibus)와 컨테이너 이미지(CNG)에 들어가는 Ruby에 직접 패치를 얹어 릴리스했고, 12일 릴리스가 크기 계산과 반복 범위 이중 해제 패치를, 21일 릴리스가 반복 ID 오버플로 패치를 더했습니다. 그리고 이틀 뒤 Ruby 본체가 같은 수정을 정식 릴리스에 담았습니다. 시스템에 따로 깔린 Ruby를 올리는 것은 GitLab 서버의 방어와 무관하고, GitLab 자체를 수정 버전으로 올려야 합니다.

서버마다 네 건 중 어디까지 닫혀 있나

이제 내 서버가 어느 칸에 있는지 볼 차례입니다. 아래 그림은 19.4 계열의 설치 버전 네 가지가 CVE 네 건 중 무엇을 막고 있는지 칸마다 색으로 보여 줍니다. 초록이 닫힌 것, 빨강이 열려 있는 것입니다.

19.4.0부터 19.4.3까지 설치 버전별로 CVE 네 건이 열려 있는지 닫혀 있는지 보여 주는 격자 그림 그림 3. 19.4 계열 버전별 상태. 19.3(19.3.3 → 19.3.5 → 19.3.6)과 19.2(19.2.7 → 19.2.8 → 19.2.9)도 같은 모양으로 한 칸씩 채워진다

네 번째 열까지 모두 초록인 줄은 맨 아래 한 줄뿐입니다. 12일 수정판인 19.4.2는 세 칸이 초록이어서 “거의 다 막았다”로 보이지만, 남은 한 칸이 가장 넓은 범위(7.0 이후)를 가진 결함입니다. 앞의 세 건은 19.2 이상만 영향을 받았기 때문에, 19.1 이하를 쓰던 서버는 이번 21일 건에서야 처음 영향권에 들어왔습니다. 이 경우엔 “이미 한 번 올렸는데”라는 말이 해당하지 않고, 처음부터 21일 수정판으로 올리면 됩니다.

12일의 문과 21일의 문, 같은 것과 달라진 것

두 번째와 세 번째 만점 결함을 항목별로 대응시켜 놓으면 바뀐 것과 그대로인 것이 갈립니다.

항목 10월 12일 건 (CVE-2026-97229) 10월 21일 건 (CVE-2026-110264)
영향 버전 19.2 이상 (19.4.2·19.3.5·19.2.8 미만) 7.0 이후 전부, 12일 수정판 포함
원인 컴파일된 패턴 크기 계산의 오버플로 반복이 많은 패턴에서 내부 ID의 오버플로
입구 저장소의 CI/CD 설정에 심은 정규식(Rapid7 시연 기준) GitLab 공지는 “조작된 정규식, 특정 조건”까지만 밝힘. 탐지 규칙 이름에 Org 문서 렌더링 오류가 있음
로그인 불필요 불필요
우회책 없음. 접근 제한으로 시연된 경로만 막힘 공식 우회책 없음
탐지 규칙 6종 2종
CVSS 10.0 10.0

바뀐 것은 원인(다른 계산), 영향 버전(19.2 이상에서 7.0 이후로), 그리고 입구입니다. 그대로인 것은 로그인이 필요 없다는 점과 10.0이라는 점입니다. 12일 건의 사전 조건은 악성 CI 설정을 심을 수 있는 쓰기 권한과 공개 프로젝트였고, 가입과 프로젝트 생성이 열린 서버라면 이 조건이 사라진다고 Rapid7이 지적했습니다.

Critical · CVSS 10.0 CVE-2026-110264 패치 있음
영향 대상
직접 설치형 GitLab CE/EE 7.0 이후 전 버전 (수정 버전 미만). GitLab.com, Dedicated는 패치 완료
공격 방식
인증 없이 네트워크로 접근, 조작된 정규식을 컴파일시켜 서버에서 임의 코드 실행(웹 워커, git 계정 권한)
점수 구성
네트워크 접근 · 쉬움 · 권한 불필요 · 사용자 조작 불필요 · 범위 변경, 기밀성·무결성·가용성 모두 높음
우회책
공식 우회책 없음. 수정 버전으로 올리는 것이 유일한 해결
  • 10월 21일 수정판(19.5.1, 19.4.3, 19.3.6, 19.2.9, 19.1.9, 19.0.10, 18.11.13)으로 업그레이드
  • 패치 전까지 공개 프로젝트 공개 범위 축소
  • GitLab이 게시한 탐지 규칙 2종 적용

Rapid7은 12일 건에서 같은 입력이 19.4.1에서는 먹히고 19.4.2에서는 먹히지 않는 것을 직접 확인했고, 공식 GitLab CE 이미지에서 git 계정 권한으로 명령이 실행되는 시연까지 만들었습니다. 12일 패치는 자기가 맡은 문을 실제로 닫았다는 뜻입니다. 효과가 없었던 것이 아니라 옆문이 열려 있었던 것입니다.

공개 사흘 뒤의 바깥 상황

21일 이후에 달라진 것이 몇 가지 있습니다. 22일에 CVE 레코드가 게시됐고(CVSS 10.0, CWE-190), 같은 날부터 GitHub에 이 결함을 겨냥한 시연 저장소가 올라오기 시작했습니다. 그중 하나는 README에서 메모리 손상으로 인한 충돌까지 보였을 뿐 코드 실행까지는 보이지 못했다고 스스로 밝히는데, 저장소 제목에 RCE가 붙어 있어도 내용이 충돌 수준에 머무는 경우가 있으니 제목만 보고 판단하지 않는 것이 좋습니다. Konfirmity의 10월 25일 갱신본은 공격 보고가 없고 악용 취약점 목록(KEV)에도 오르지 않았다고 정리합니다.

입구에 대해서는 GitLab 공지가 “특정 조건”이라고만 했고, 탐지 규칙 이름에 있는 “Org mode render error burst”와 외부 정리 글들이 가리키는 쪽은 Org 문서(.org)를 렌더링하는 단계입니다. 정리한 글들에 따르면 문서 안의 문자열로 정규식을 만드는 Ruby gem이 렌더링 중 호출되고, 로그인 없이 볼 수 있는 공개 프로젝트의 문서가 닿을 수 있는 입력이 됩니다. 이 글은 공격 방법을 따라 하는 글이 아니므로 여기까지만 다루고, GitLab은 이슈 상세를 패치 90일 뒤인 2027년 1월 19일경에 공개할 예정입니다. 상세가 풀리면 공격 코드를 만들기가 쉬워지니 그 전에 올려 두는 것이 맞습니다.

시연 코드가 돌아다니는 지금은 우선순위가 달라집니다. 인터넷에 열려 있고 공개 프로젝트를 둘 수 있는 서버부터 올리고, 사내망 전용 서버는 다음 점검 시간에 맞추면 됩니다.

올리는 날의 여섯 단계

공식 업그레이드 문서가 권하는 흐름을 이번 건에 맞춰 줄이면 아래와 같습니다. 버전 확인은 읽기 전용이고 설치 명령만 서버를 바꿉니다.

  1. 설정과 비밀 파일을 포함한 전체 백업을 만들거나 서버 스냅샷을 찍습니다. 패키지 설치가 데이터베이스를 자동 백업하더라도 이것을 전체 백업으로 여기지 않습니다.
  2. 백그라운드 마이그레이션이 끝났는지 확인합니다. 진행 중인 채로 다음 버전을 올리면 안 됩니다.
  3. 점검 모드를 켜고 CI/CD 파이프라인과 작업을 잠시 멈추는 것을 공식 문서가 권합니다.
  4. 같은 계열의 수정 버전을 지정해 설치합니다(아래 명령).
  5. GitLab Runner를 올린 GitLab 버전과 같은 버전으로 맞춥니다.
  6. 점검 모드를 끄고 파이프라인을 다시 열고, 상태 점검 명령으로 확인합니다.
# 지금 버전 확인(읽기 전용)
sudo gitlab-rake gitlab:env:info | grep -i "GitLab information" -A3

# Ubuntu·Debian 예: 19.4 계열이면 19.4.3 지정(EE는 gitlab-ee=19.4.3-ee.0)
sudo apt update && sudo apt install gitlab-ce=19.4.3-ce.0

# RHEL 계열 예(9, EE는 gitlab-ee-19.4.3-ee.0.el9)
sudo dnf install gitlab-ce-19.4.3-ce.0.el9

# 올린 뒤 상태 점검
sudo gitlab-rake gitlab:check

관리자 토큰이 있으면 API로도 버전을 읽을 수 있습니다. 응답의 version이 19.4.2-ee 같은 모양으로 나옵니다(예시).

curl --header "PRIVATE-TOKEN: <토큰>" "https://gitlab.example.com/api/v4/version"

19.4.3과 19.3.6에는 DB 마이그레이션이 들어 있고, 19.4.3에는 배포 후 마이그레이션도 있습니다. 노드가 하나뿐인 서버는 마이그레이션이 끝날 때까지 서비스가 멈추니 점검 공지부터 내고 사용자가 적은 시간대에 진행합니다. 여러 노드로 운영한다면 Linux 패키지 다중 노드 구성에 한해 무중단 업그레이드 절차를 쓸 수 있고, 순서는 뒤쪽부터 Consul, PostgreSQL, PgBouncer, Redis, Gitaly, Praefect, 그다음 Rails와 Sidekiq입니다. 한 번에 마이너 릴리스 하나씩 올리며 배포 후 마이그레이션은 지정 노드에서 실행합니다. 고가용성으로 구성되지 않은 구성요소는 점검 시간을 두고 올려야 하고, 데이터베이스가 10GB 미만이면 약 한 시간이 걸린다는 것이 공식 문서의 시험 결과입니다. 이 시간은 환경에 따라 다르니 어림값으로만 보세요.

수정본 전까지 줄일 수 있는 노출

올리기까지 며칠이 걸린다면 공격이 들어오는 길을 좁히는 것이 먼저입니다. 이것은 공식 우회책이 아니라 시간을 버는 조치입니다. 바깥에서 안쪽으로 네 가지를 겹치면 됩니다.

  • 접근 주소 제한: 인터넷에 직접 열어 두었다면 사내망이나 VPN으로 좁힙니다. 낯선 접속 자체가 줄어듭니다.
  • 가입 제한: 관리자 영역의 General 설정에서 New user account restrictions를 열어 새 계정 허용을 끄거나 관리자 승인을 요구합니다.
  • 공개 범위 축소: Visibility and access controls의 Restricted visibility levels에서 Public을 제한합니다. 이미 공개인 프로젝트는 각각 비공개나 내부 공개로 바꿔야 합니다.
  • 탐지: GitLab이 게시한 규칙 “Onigmo native worker crash”와 “Org mode render error burst”를 로그 감시에 넣습니다.

공개 범위 제한에는 주의가 필요합니다. Public을 제한하면 공개 그룹·프로젝트·스니펫을 만드는 일이 관리자에게만 열리지만, 이 제한은 개인 네임스페이스 아래 프로젝트에는 적용되지 않고 이미 만들어진 공개 프로젝트에도 소급되지 않습니다. 기본 프로젝트 가시성으로 지정된 단계는 제한 목록에 넣을 수 없습니다. 신뢰하지 않는 사용자의 프로젝트 생성 권한은 Default minimum role required to create projects에서 No one이나 Administrators로 좁힙니다. Rapid7은 12일 건에서 이런 제한이 시연된 경로만 막을 뿐 컴파일러 자체를 고치지는 않는다고 짚었으니, 임시 조치는 올리는 날까지만 쓰세요.

로그에서 찾는 시도의 흔적

패치 전에 시도가 있었는지는 로그로 가늠합니다. Rapid7이 12일 건에서 든 징후는 네 가지입니다. 오래 걸린 CI 린트 요청이 502로 끝나고 Workhorse 로그에 백엔드 연결 EOF가 찍히는 것, 같은 시각에 웹 서버(Puma) 워커가 죽거나 재시작되는 것(스택 추적에 정규식 매처가 보이면 더 의심), 워커 메모리가 약 2GiB 늘어나는 것, 예상하지 못한 셸 자식 프로세스입니다. 아래는 모두 읽기 전용 검색입니다.

# Workhorse가 백엔드 연결 끊김(EOF)을 기록한 줄
sudo grep -i "eof" /var/log/gitlab/gitlab-workhorse/current | tail -n 20

# Puma가 정규식 관련 스택을 남긴 줄
sudo grep -i "regexp" /var/log/gitlab/puma/puma_stderr.log | tail -n 20

# Rails 요청 로그에서 502로 끝난 요청 수
sudo grep -c '"status":502' /var/log/gitlab/gitlab-rails/production_json.log

GitLab도 직접 설치형용 탐지 규칙을 공개했습니다. 12일 건에는 6종(Onigmo native worker crash, Graphql cilint hostile regexp, ci regexp oversized non ascii path, ci regexp guard rejection, ci lint workhorse worker crash, ci lint scripted client error burst)이, 21일 건에는 2종(Onigmo native worker crash, Org mode render error burst)이 있고 로직 설명은 공지에 없습니다. 규칙이 시연된 경로를 기준으로 하므로 흔적이 없다고 안전한 것은 아닙니다. 패치가 끝나야 닫힌 것입니다.

패치 전에 이미 뚫렸을 가능성을 의심한다면 SOC Prime이 정리한 사후 징후도 볼 만합니다. GitLab 서비스 계정 아래에서 도는 셸·스크립트 프로세스, 새 SSH 키나 관리자 계정, 예약 작업의 변경, 러너·배포 토큰·액세스 토큰의 변경, 예상 밖의 저장소·파이프라인 수정, 서버에서 나가는 낯선 연결입니다. 하나라도 걸리면 서버를 격리하고 증거를 남긴 뒤 토큰과 자격 증명을 교체합니다.

같은 릴리스에 실린 나머지 11건

21일 릴리스는 모두 12건을 고칩니다. 치명 1건 말고는 High 2건, Medium 5건, Low 4건입니다. 아래 그림은 12건의 CVSS를 줄 세운 것이고, 한눈에 10.0 하나가 나머지와 얼마나 떨어져 있는지 보입니다.

21일 릴리스가 고친 12건의 CVSS 점수를 등급별 색으로 내림차순 막대로 놓은 그림 그림 4. 21일 릴리스의 CVSS 3.1 기본 점수. 막대 오른쪽이 등급

CVE 등급 내용 해당 버전부터
CVE-2026-110264 Critical 정규식 컴파일러 정수 오버플로(이 글의 주제) 7.0
CVE-2026-15723 High OmniAuth와 LDAP 자동 연결의 이메일 조회 인증 결함 10.1
CVE-2026-112212 High OAuth/OIDC 탐색 엔드포인트 캐시 오염 18.3
CVE-2026-12664 Medium GraphQL 작업 항목 이메일 필드의 접근 통제(read_api 범위 우회) 18.2
CVE-2026-16255 Medium 인스턴스 전체 SAML/LDAP 멤버십 잠금 불완전(EE) 12.0
CVE-2026-105777 Medium 내부 응답 헤더로 내부 자격 증명 노출 17.6.5
CVE-2026-13319 Medium 그룹 마일스톤 API 권한 우회 15.10
CVE-2026-112378 Medium AI Gateway 기능 활성화 헤더의 신뢰 수준(EE) 17.8
CVE-2026-105711 Low MR 제목 렌더링 조각 캐시에 민감 정보 15.0
CVE-2026-14288 Low MR 승인 정책 집행의 접근 통제(EE) 17.4
CVE-2026-112326 Low 보안 결과에서 예외 시 정리 누락(EE) 17.8
CVE-2026-103515 Low 그룹 Duo 관리자 잠금 설정의 접근 통제(EE) 19.2

눈여겨볼 항목은 두 개의 High입니다. CVE-2026-15723(CVSS 8.2)은 SAML과 LDAP 자동 연결을 함께 켠 서버에서 로그인한 사용자가 LDAP 기반 계정을 탈취할 수 있던 결함이고, CVE-2026-112212(CVSS 7.5)는 OAuth/OIDC 탐색 문서의 캐시 오염으로 로그인 흐름이 외부 서버로 넘어갈 수 있던 결함입니다. 이 11건은 19.5.1, 19.4.3, 19.3.6에만 들어 있고 19.2 이하 백포트(19.2.9, 19.1.9, 19.0.10, 18.11.13)에는 치명 1건만 담깁니다. 로그인 연동을 쓰는 서버라면 가능한 한 19.3 이상으로 올리는 편이 낫습니다. 19.2 이하에서 치명 1건만 막으면 나머지 11건은 그대로 남는다는 뜻이기도 합니다.

Ruby로 만든 앱에서 찾을 입구 네 곳

이 결함의 뿌리는 GitLab 코드가 아니라 Ruby의 정규식 엔진이라, Ruby 본체도 23일에 고쳐졌습니다. Ruby 4.0.9, 3.4.12, 3.3.13이 네 건의 원인 버그를 모두 담았고, 보통 보안 수정만 받는 3.3도 GitLab이 CVE를 붙였기 때문에 예외로 포함됐습니다. Ruby 쪽은 CVE를 따로 신청하지 않았고, 당분간 GitLab이 붙인 번호로 스캐너에서 추적하라고 안내합니다. GitLab이 Ruby에 직접 패치를 얹은 곳은 자기 패키지와 컨테이너 이미지 빌드이므로, 패키지 없이 소스로 설치해 Ruby를 직접 관리하는 서버라면 위 Ruby 버전을 직접 올려야 합니다.

영향 범위는 한 가지 조건으로 정해집니다. 공격자가 쓴 문자열로 정규식을 만드는 앱만 대상이고, 개발자가 직접 쓴 정규식만 쓰는 앱은 해당하지 않습니다. 입구는 네 가지 호출입니다. 사용자 입력을 그대로 패턴으로 만드는 Regexp.new(입력)과 같은 동작의 다른 이름인 Regexp.compile(입력), 여러 입력을 하나로 합치는 Regexp.union(입력들), 정규식 리터럴 안에 입력을 문자열로 끼워 넣는 /#{입력}/입니다.

시간 제한과 길이 제한은 방패가 되지 않습니다. Ruby는 Regexp.timeout이 서비스 거부를 막는 장치일 뿐 이번 버그에는 소용이 없고, 짧은 패턴으로도 발동하는 버그가 있어 길이 제한도 믿을 수 없다고 밝혔습니다. 업그레이드가 어려우면 신뢰할 수 없는 입력으로 정규식을 만들지 않는 것이 유일한 대안입니다. 내 앱 코드에 그런 호출이 있는지는 읽기 전용 검색으로 확인합니다. 결과가 없으면 위 입구가 없다는 뜻이고, 있으면 그 입력이 외부에서 오는지부터 따져 봅니다.

grep -rnE "Regexp\.(new|compile|union)\(" app lib

계열별 수정판 일람

네 번의 릴리스를 계열별로 늘어놓은 표입니다. 내가 쓰는 계열의 줄을 따라 오른쪽 끝까지 가면 목표 버전이 나옵니다. 가운데 칸의 “—“는 그날 그 계열에는 이 건들의 수정판이 나오지 않았다는 뜻입니다.

지금 쓰는 계열 9월 23일 10월 12일 10월 21일(목표) 21일 수정판에 담긴 것
19.5 — — 19.5.1 12건 전부
19.4 19.4.1 19.4.2 19.4.3 (DB 마이그레이션 + 배포 후 마이그레이션) 12건 전부
19.3 19.3.3 19.3.5 19.3.6 (DB 마이그레이션) 12건 전부
19.2 19.2.7 19.2.8 19.2.9 치명 1건만
19.1 — — 19.1.9 치명 1건만
19.0 — — 19.0.10 치명 1건만
18.11 — — 18.11.13 치명 1건만
18.10 이하 — — 수정본 없음 지원되는 계열로 먼저 이동

Ruby를 직접 관리하는 앱이라면 10월 23일에 나온 수정판이 목표입니다.

Ruby 계열 네 건의 원인 버그가 모두 들어간 첫 릴리스 게시
4.0 4.0.9 10월 23일 03:11 UTC
3.4 3.4.12 10월 23일 03:11 UTC
3.3 3.3.13 (보안 전용 계열이지만 이번에는 예외 포함) 10월 23일 03:11 UTC
#GitLab#CVE-2026-110264#CVE-2026-97229#정규식 엔진#원격 코드 실행