
GitLab CVE-2026-97229: Lỗ hổng RCE CVSS 10.0 không cần đăng nhập — Kiểm tra và vá ngay trước 1/11

Ngày 29/10/2026, Cơ quan An ninh mạng và Hạ tầng Hoa Kỳ (CISA) đã đưa lỗ hổng CVE-2026-97229 của GitLab vào danh mục lỗ hổng đang bị khai thác thực tế (KEV), với hạn khắc phục 1/11/2026 cho các cơ quan liên bang Mỹ. Đây là lỗ hổng đạt điểm tối đa CVSS 10.0: kẻ tấn công không cần tài khoản, không cần mật khẩu, vẫn có thể thực thi mã tùy ý (RCE) trên máy chủ GitLab chỉ bằng một biểu thức chính quy (regex) được chế tác trong file cấu hình CI/CD.
Và đây không còn là lý thuyết: mã khai thác mẫu (PoC) đã công khai từ 13/10, và một kẻ tấn công thật sự đã thử khai thác lỗ hổng này nhắm vào máy chủ GitLab của chính dự án Alpine Linux. Nếu bạn đang tự host GitLab (self-hosted), bài này dành cho bạn — gồm cả một cạm bẫy khiến Alpine Linux “nâng cấp rồi mà vẫn dính”.
1. Chuyện gì vừa xảy ra?
- 12/10/2026: GitLab phát hành bộ bản vá khẩn cấp 19.4.2, 19.3.4 và 19.2.8, sửa 24 lỗ hổng bảo mật. Nghiêm trọng nhất là CVE-2026-97229 (CVSS 10.0), do nhà nghiên cứu Johan Carlsson (joaxcar) báo cáo qua chương trình HackerOne.
- 13/10/2026: Rapid7 công bố mã khai thác mẫu chạy thành công trong phòng lab: thực thi lệnh với quyền user
gittrên GitLab 19.4.1 chưa vá. - 20–21/10/2026: Một tài khoản mới đăng ký gửi các cấu hình CI độc hại vào GitLab của Alpine Linux, làm tiến trình worker sập 8 lần; trong 4 lần, kẻ tấn công tiến được nửa chặng đường khai thác rồi thất bại ở bước tiếp theo.
- 23/10/2026: Ruby phát hành 3.3.13, 3.4.12 và 4.0.9 — bản vá cho engine regex nằm bên dưới lỗ hổng này (mấu chốt của mục 4).
- 28/10/2026: Alpine Linux công bố hậu kiểm (post-mortem): không tìm thấy bằng chứng bị xâm nhập thành công nhưng cũng không thể loại trừ, nên họ dựng lại máy chủ từ đầu, thay khoá bí mật và đặt lại mật khẩu mọi tài khoản.
- 29/10/2026: CISA đưa CVE-2026-97229 vào KEV, hạn khắc phục 1/11/2026. GitLab cũng phát hành bộ quy tắc phát hiện (threat detections) cho khách hàng self-managed sau khi ghi nhận các nỗ lực khai thác.
Đáng chú ý, đây là lỗ hổng thứ ba trong cùng một engine regex của GitLab chỉ trong hơn một tháng — và là lỗ hổng đầu tiên trong nhóm này không cần đăng nhập.
2. CVE-2026-97229 là gì? Vì sao một regex lại thành RCE?
GitLab dùng Ruby để biên dịch các biểu thức chính quy trong cấu hình CI/CD — ví dụ điều kiện rules:if hay mẫu khớp đường dẫn file trong .gitlab-ci.yml. Engine làm việc này là Onigmo, engine regex tích hợp sẵn trong Ruby.
Khi biên dịch một pattern, Onigmo phải tính trước xem cần cấp bao nhiêu bộ nhớ. Lỗi nằm đúng ở phép tính đó: với một pattern được chế tác khéo, con số kích thước bị tràn số nguyên (integer overflow, CWE-190) — nó “vòng” lại thành một giá trị rất nhỏ, khiến engine cấp vùng nhớ nhỏ hơn nhiều so với thực tế cần. Quá trình biên dịch sau đó ghi tràn bộ nhớ (memory corruption), và từ đó kẻ tấn công có thể điều khiển luồng thực thi để chạy mã tùy ý trên máy chủ, với quyền của user git.
GitLab chấm lỗ hổng này CVSS 3.1 ở mức 10.0/10 (vector AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H): tấn công qua mạng, độ phức tạp thấp, không cần quyền, không cần nạn nhân thao tác — và hậu quả là chiếm trọn máy chủ.
Có một điểm cần hiểu đúng về nhãn “không cần đăng nhập”. Theo phân tích của Rapid7, đường khai thác đã công bố cần gửi lên một project công khai gồm file .gitlab-ci.yml độc hại kèm đường dẫn file chứa ký tự UTF-8; riêng request CI lint ở bước cuối thì không cần xác thực. Nhưng trên các máy chủ cho phép tự đăng ký tài khoản và tạo project công khai (cấu hình cực kỳ phổ biến), kẻ tấn công chỉ mất một phút để có tài khoản — nên thực tế vẫn là không cần đăng nhập, đúng như cách Alpine Linux bị dò trúng.
Đây cũng là lỗi regex thứ ba liên tiếp của GitLab: ngày 23/9, hãng đã vá CVE-2026-89078 (double-free, 9.9) và CVE-2026-93577 (tràn số, 9.9) trong cùng engine — nhưng cả hai đều cần tài khoản đăng nhập. Lần này, “cửa” đăng nhập biến mất hoàn toàn.

3. Ai bị ảnh hưởng?
Lỗ hổng ảnh hưởng GitLab Community Edition (CE) và Enterprise Edition (EE) bản tự quản (self-managed) ở ba nhánh sau:
| Nhánh GitLab | Phiên bản bị ảnh hưởng | Bản vá tối thiểu | Bản mới nhất của nhánh (phát hành 21/10) |
|---|---|---|---|
| 19.2 | 19.2.0 đến 19.2.7 | 19.2.8 | 19.2.9 |
| 19.3 | 19.3.0 đến 19.3.4 | 19.3.5 | 19.3.6 |
| 19.4 | 19.4.0 đến 19.4.1 | 19.4.2 | 19.4.3 |
Hai lưu ý rất quan trọng trong bảng này:
- Đang ở 19.3.4 thì đừng tưởng đã vá. Khi mới công bố ngày 12/10, GitLab ghi 19.3.4 là bản vá cho nhánh 19.3. Nhưng sau đó hãng đã xếp lại 19.3.4 vào nhóm bị ảnh hưởng (bản này vướng một lỗi khác liên quan trang merge request và tích hợp Ona) và khuyến nghị lên 19.3.5 trở lên. Đang ở 19.3.4 thì hãy nâng tiếp lên 19.3.5, tốt nhất là 19.3.6.
- Nhánh 19.5 không nằm trong diện ảnh hưởng của CVE-2026-97229. Tuy vậy, bản 19.5.1 (21/10) vá một lỗi regex khác — CVE-2026-110264 — cũng đạt CVSS 10.0, nên đang ở 19.5 bạn vẫn nên cập nhật.
Không bị ảnh hưởng: người dùng GitLab.com (đã được vá sẵn, bạn không cần làm gì) và khách hàng GitLab Dedicated. Vấn đề chỉ nằm ở bản GitLab tự cài, tự vận hành.
Nhóm rủi ro cao nhất là các máy chủ GitLab self-hosted lộ ra internet (theo Shadowserver, có gần 2.800 instance GitLab CE như vậy) và cho phép người lạ tự đăng ký tài khoản. Nhóm thứ hai — dễ bị bỏ sót hơn nhiều — là các bản cài từ mã nguồn (source) hoặc chạy image tự build với Ruby riêng. Lý do nằm ở mục tiếp theo.
4. Bài học Alpine Linux: nâng cấp GitLab rồi mà vẫn chưa vá xong
Vụ việc ở Alpine Linux cho thấy vì sao CVE này nguy hiểm theo cách rất khó lường:
- Ngày 13/10, Alpine nâng máy chủ lên GitLab 19.3.4 thay vì đi tiếp lên 19.3.5 — chính họ thừa nhận đây là một sai lầm. Máy chủ vì thế chưa có lớp vá hoàn chỉnh khi bị dò vào ngày 20/10.
- Ngày 22/10 — giữa lúc bị tấn công — Alpine nâng tiếp lên 19.3.6, nhưng đến 26/10 họ phát hiện máy chủ vẫn dính lỗ hổng. Nguyên nhân: bản vá của GitLab nằm trong Ruby được đóng gói kèm gói cài đặt và image chính thức của GitLab, trong khi image của Alpine dùng Ruby “zin” (bản Ruby chuẩn) chưa được vá. Nâng GitLab không hề đụng tới Ruby riêng đó.
- Tới khi image 19.3.6 được phát hành lại vào 27/10 với Ruby 3.3.13, bản vá mới thật sự có hiệu lực. Nghĩa là: ai đã pull image 19.3.6 trước ngày 27/10 — và mọi tag cũ hơn — vẫn đang hở và phải pull lại.
- Alpine kết luận không thể chứng minh cuộc tấn công có thành công hay không, vì theo lời họ, một lần khai thác thành công sẽ không gây sập tiến trình và không để lại dấu vết trong web log; một phần log của ngày bị tấn công cũng đã mất. Họ chọn phương án an toàn nhất: coi máy chủ như đã bị xâm nhập — dựng lại từ đầu, thay toàn bộ khoá bí mật, đặt lại mật khẩu mọi tài khoản và đối chiếu lại các package đã build trong giai đoạn bị tấn công bằng dữ liệu nằm ngoài GitLab.
Hai bài học rút ra: một, đọc kỹ advisory đến tận lớp phụ thuộc bên dưới — “đúng phiên bản GitLab” chưa chắc đã đủ nếu cách cài của bạn tách riêng Ruby; hai, vắng dấu vết không đồng nghĩa với an toàn với lỗ hổng này.
5. Kiểm tra phiên bản GitLab của bạn trong 2 phút
Cách 1: Từ giao diện quản trị (Admin Area). Đăng nhập bằng tài khoản admin, mở trang Admin Area (thường tại /admin). Dòng đầu tiên của trang đã hiển thị phiên bản GitLab bạn đang chạy. Nếu bạn dùng GitLab self-managed, trang này có mục Components liệt kê phiên bản của từng thành phần đi kèm.
Cách 2: Từ terminal trên máy chủ, dùng lệnh truy vấn trực tiếp. Đây là cách chính xác nhất nếu bạn quản lý máy chủ:
# Omnibus (phổ biến nhất, gói cài đặt của GitLab)
sudo gitlab-rake gitlab:env:info
# Docker (chạy lệnh vào container)
docker exec -it gitlab gitlab-rake gitlab:env:info
# Chỉ cần xem số phiên bản GitLab
cat /opt/gitlab/embedded/service/gitlab-rails/VERSION
Cách 3: Đối chiếu Ruby và thời điểm pull image. Nếu bạn dùng Docker hoặc Helm:
# Kiểm tra Ruby mà container đang chạy
docker exec -it gitlab ruby -v
# Nếu image 19.3.6 được pull trước ngày 27/10/2026, hãy pull lại
# và kiểm tra Ruby mới là 3.3.13
docker pull gitlab/gitlab-ee:19.3.6-ee.0
docker exec -it gitlab ruby -v
# Kết quả kỳ vọng: ruby 3.3.13
Nguyên tắc đối chiếu Ruby, lấy từ chính bảng phiên bản của Ruby:
- GitLab 19.3/19.4 chạy Ruby 3.3.x: cần 3.3.13 trở lên.
- GitLab 19.5 chạy Ruby 3.4.x: cần 3.4.12 trở lên.
- GitLab 19.6 chạy Ruby 4.0.x: cần 4.0.9 trở lên.
Nếu phiên bản GitLab của bạn thấp hơn bản vá tối thiểu hoặc Ruby chưa đạt mốc, máy chủ vẫn đang hở.

Máy GitLab kiểm tra trong môi trường giả lập cho kết quả: GitLab 19.4.1 (bị ảnh hưởng) và Ruby 3.3.8 (dưới mốc vá 3.3.13). Máy của bạn mà tương tự thì chuyển ngay sang mục 6.
Trước khi nâng cấp, bắt buộc phải sao lưu: nếu bỏ qua bước này và quá trình nâng cấp lỗi giữa chừng, bạn sẽ phải quay lại từ đầu mà không có đường lui.
6. Nâng cấp từng bước
Bước 0 — Sao lưu toàn bộ (không thể bỏ qua).
# Sao lưu GitLab (Omnibus)
sudo gitlab-backup create
# Docker
docker exec -t gitlab gitlab-backup create
Tài liệu chính thức khuyên nên có bản sao lưu của toàn bộ hệ thống, bao gồm cấu hình, dữ liệu ứng dụng, các bản ghi và khoá bí mật. Thử khôi phục trên máy kiểm tra trước khi bạn cần đến nó thật sự.
Bước 1 — Xác định lộ trình nâng cấp của bạn. GitLab có quy tắc riêng: nếu bạn đang ở bản quá cũ, không được nâng thẳng lên bản mới nhất. Cách an toàn:
- Đang ở 19.2: đi theo lộ trình 19.2.8 → 19.2.9 → (sau đó) các bản mới hơn.
- Đang ở 19.3: lên 19.3.5 rồi 19.3.6 (lưu ý trường hợp image cũ trước 27/10).
- Đang ở 19.4: lên 19.4.2, sau đó lên 19.4.3.
- Đang ở 19.5: lên 19.5.1.
Bước 2 — Nâng cấp theo phương thức bạn đang dùng.
# Omnibus (Ubuntu/Debian) — chuyển tới tag mới
# Ví dụ: nâng lên 19.4.3-ee.0
sudo apt update && sudo apt install gitlab-ee=19.4.3-ee.0
sudo gitlab-ctl reconfigure
# Docker — kéo image mới rồi tạo lại container
docker pull gitlab/gitlab-ee:19.4.3-ee.0
docker stop gitlab && docker rm gitlab
docker run --detach \
--hostname gitlab.example.com \
--publish 443:443 --publish 80:80 --publish 22:22 \
--name gitlab \
--volume $GITLAB_HOME/config:/etc/gitlab \
--volume $GITLAB_HOME/logs:/var/log/gitlab \
--volume $GITLAB_HOME/data:/var/opt/gitlab \
gitlab/gitlab-ee:19.4.3-ee.0
Với Helm (Kubernetes) thì cập nhật chart lên tag tương ứng; nếu nâng cả phiên bản chính (major), kiểm tra đường dẫn nâng cấp và các thay đổi phá vỡ (breaking changes) trước.
Bước 3 — Xác minh bản vá đã có hiệu lực.
# Kiểm tra lại phiên bản GitLab
sudo gitlab-rake gitlab:env:info
# Kiểm tra lại Ruby trong container
docker exec -it gitlab ruby -v
# GitLab 19.3/19.4 → kỳ vọng ruby 3.3.13 trở lên
Bước 4 — kiểm tra lại sau nâng cấp: mở /help hoặc chạy lại các lệnh ở mục 5 để xác nhận phiên bản đích, rồi kiểm tra dịch vụ bằng sudo gitlab-ctl status.

Nói thẳng: GitLab không công bố workaround chính thức nào cho CVE-2026-97229 — nâng cấp là cách xử lý triệt để duy nhất. Các biện pháp ở mục sau chỉ giúp bạn cầm cự trong lúc chờ cửa sổ bảo trì.
7. Chưa nâng cấp được ngay? 5 lớp giảm nhẹ tạm thời
Các biện pháp này làm giảm khả năng khai thác hoặc hạn chế hậu quả, nhưng không thay thế việc nâng cấp:
- Tắt đăng ký tự do (self-registration). Nếu không bắt buộc phải mở đăng ký công khai, hãy tắt ngay — đây là mấu chốt trong vụ Alpine. Vào Settings → Sign-up restrictions và tắt
Sign-up enabled. Nếu vẫn cần đăng ký, yêu cầu admin phê duyệt tài khoản (Require admin approval) và giới hạn tên miền email được phép. - Hạn chế tạo project công khai. Đặt Visibility level mặc định của project mới thành Private, và hạn chế quyền tạo project công khai cho nhóm được kiểm soát. Đường khai thác công bố nhắm vào project công khai, nên đóng lối này sẽ gây khó khăn đáng kể cho kẻ tấn công.
- Đặt GitLab sau lớp mạng riêng hoặc giới hạn IP. Dùng firewall, VPN hoặc reverse proxy chỉ cho phép dải IP nội bộ/công ty truy cập. Kẻ tấn công phải chạm được tới máy chủ thì mới khai thác được, và lớp mạng là rào chắn đầu tiên.
- Chặn hoặc giám sát endpoint CI Lint. Nếu không thể nâng cấp, kiểm tra log truy cập CI Lint để phát hiện request bất thường với đường dẫn file chứa UTF-8 hoặc cấu hình CI có
rules:ifphức tạp — đây là dấu vết có thể lần theo được, dù không phải lúc nào cũng ghi lại. - Kích hoạt phát hiện (threat detection) của GitLab. Ngày 29/10, GitLab phát hành bộ quy tắc phát hiện các nỗ lực khai thác CVE-2026-97229 cho khách hàng self-managed. Cập nhật bộ quy tắc này và giám sát cảnh báo thường xuyên.
8. Nếu nghi ngờ máy chủ đã bị xâm nhập
Đừng chỉ “quét virus rồi thôi”. Với lỗ hổng này, kẻ tấn công có thể chiếm quyền git trên máy chủ và từ đó lần ra khoá bí mật, token, thông tin đăng nhập CI và các runner. Theo hậu kiểm của Alpine, các bước họ làm là:
- Coi máy chủ như đã bị xâm nhập: dựng lại máy chủ từ đầu trên bản đã vá.
- Xoá và tạo lại mọi khoá bí mật: các biến CI, token runner, khoá SSH, khoá deploy và thông tin đăng nhập của người dùng.
- Đặt lại mật khẩu mọi tài khoản, đặc biệt là các tài khoản admin và bot.
- Kiểm tra lại toàn bộ dữ liệu được tạo trong khoảng thời gian máy chủ chưa vá: vì kẻ tấn công có thể đã chèn mã độc vào các artifact đã build trong thời gian đó, chỉ đối chiếu với dữ liệu nằm ngoài GitLab (ví dụ checksum, log build độc lập) mới xác minh được.
Nếu bạn không chắc chắn, hãy liên hệ đội ứng cứu sự cố (incident response) trước khi đưa máy chủ trở lại hoạt động.
9. FAQ
CVE-2026-97229 có cần đăng nhập không?
Về kỹ thuật, request CI lint ở bước cuối của đường khai thác đã công bố không cần xác thực. Thực tế, trên các máy chủ cho phép tự đăng ký và tạo project công khai, kẻ tấn công vẫn có thể tự tạo tài khoản trong một phút. Vì vậy, hãy coi đây là lỗ hổng không cần đăng nhập.
Tôi dùng GitLab.com có cần làm gì không?
Không. GitLab.com đã được vá. Chỉ các máy chủ tự quản (self-managed) mới cần nâng cấp.
Tôi đang ở 19.3.4, có cần nâng cấp tiếp không?
Có. 19.3.4 nằm trong diện bị ảnh hưởng. Hãy lên 19.3.5 trở lên, tốt nhất là 19.3.6 (nhưng nếu image 19.3.6 được pull trước 27/10, hãy pull lại và kiểm tra Ruby là 3.3.13).
Nâng cấp GitLab là đủ chưa?
Chưa chắc. Nếu bạn dùng image tự build hoặc cài từ mã nguồn với Ruby riêng, cần kiểm tra Ruby đã đạt mốc 3.3.13 (nhánh 3.3.x), 3.4.12 (nhánh 3.4.x) hoặc 4.0.9 (nhánh 4.0.x) chưa.
Có workaround nào không?
Không có workaround chính thức. Các biện pháp giảm nhẹ trong mục 7 chỉ làm giảm rủi ro, không vá được lỗ hổng. Cách duy nhất để vá là nâng cấp.
Hạn khắc phục là khi nào?
CISA yêu cầu các cơ quan liên bang Mỹ khắc phục trước 1/11/2026. Dù bạn không thuộc diện bắt buộc, đây vẫn là thời hạn hợp lý để hành động — mã khai thác đã công khai và các cuộc tấn công thật đã xảy ra.
10. Kết luận
CVE-2026-97229 là lỗ hổng hiếm hoi đạt CVSS 10.0 mà không cần đăng nhập, có mã khai thác công khai và đã có kẻ tấn công thật sự nhắm vào một dự án mã nguồn mở lớn. Nếu bạn tự host GitLab, hãy kiểm tra phiên bản ngay hôm nay, đối chiếu cả Ruby, và nâng cấp lên bản đã vá trước 1/11.
Và nhớ bài học của Alpine: nâng cấp GitLab chưa chắc đã là vá xong — hãy kiểm tra cả lớp phụ thuộc bên dưới.
Nguồn tham khảo
- GitLab — Security Release: 19.4.2, 19.3.4, 19.2.8 (12/10/2026)
- CISA — Known Exploited Vulnerabilities Catalog: CVE-2026-97229
- Ruby — Ruby 3.3.13, 3.4.12, 4.0.9 Released (23/10/2026)
- The Hacker News — GitLab Patches Critical Unauthenticated RCE Flaw (CVE-2026-97229)
- The Hacker News — CISA Adds GitLab RCE Flaw to KEV Catalog
- BleepingComputer — GitLab patches critical unauthenticated RCE vulnerability
- Censys — GitLab CVE-2026-97229: unauthenticated RCE

Bình luận (0)