"Sức mạnh phi lý" của VEX trên NixOS: Tự động hóa việc phân loại lỗ hổng bảo mật
Làn sóng báo cáo lỗ hổng do LLM hỗ trợ đang khiến các đội ngũ bảo mật quá tải. Bài viết phân tích cách tài liệu VEX (Vulnerability Exploitability eXchange) có thể tự động hóa quy trình phân loại CVE, và lý do NixOS trở thành môi trường lý tưởng để hiện thực hóa ý tưởng này thông qua dự án mã nguồn mở nixos-vex.
"Sức mạnh phi lý" của VEX trên NixOS: Tự động hóa việc phân loại lỗ hổng bảo mật
Năm nay, làn sóng báo cáo lỗ hổng bảo mật được hỗ trợ bởi các mô hình ngôn ngữ lớn (LLM) đã tạo ra áp lực khổng lồ lên cộng đồng mã nguồn mở. Trong khi các maintainer (người duy trì dự án) vật lộn để xử lý đống báo cáo, thì ở phía bên kia quy trình, các đội SysAdmin, SRE và AppSec cũng đang chìm trong làn sóng CVE mới xuất hiện mỗi ngày. Liệu tài liệu VEX có thể là giải pháp tự động hóa giúp phân loại lỗ hổng ở quy mô lớn — và tại sao NixOS lại tỏ ra đặc biệt hiệu quả trong việc này?
Khi làn sóng CVE khiến cả hai phía đều kiệt sức
Câu chuyện bắt đầu từ một nghịch lý quen thuộc. Các dự án mã nguồn mở phổ biến đang phải giảm tốc độ phát triển tính năng để tập trung vào việc phân loại lỗ hổng. Một số dự án vẫn đang loay hoay tìm cách chống lại chính làn sóng báo cáo đó.
Nhưng chúng ta thường nghe nhiều về phía maintainer, mà ít nghe về phía còn lại: các đội vận hành và bảo mật ứng dụng. Mỗi CVE mới (có thể chưa có bản vá) đều cần được đánh giá, và phần mềm bị ảnh hưởng phải được cập nhật hoặc vá thủ công. Khối lượng công việc này tăng theo cấp số nhân.
Đây là lúc VEX — viết tắt của Vulnerability Exploitability eXchange — xuất hiện. Đây là một dạng tư vấn bảo mật mà máy có thể đọc được, cho biết liệu một sản phẩm phần mềm cụ thể có thực sự bị phơi nhiễm trước một lỗ hổng đã biết hay không. Nghe rất hứa hẹn, nhưng câu hỏi đặt ra là: liệu chúng ta có thể tạo ra các tuyên bố VEX này một cách tự động để hỗ trợ quy trình phân loại lỗ hổng có khả năng mở rộng?
Quy trình quét dựa trên SBOM và những hạn chế
Hãy xem xét một quy trình bảo mật được nhiều dự án và tổ chức sử dụng hiện nay. Với một chương trình Go đơn giản sử dụng thư viện golang.org/x/text phiên bản v0.38.0, quy trình phổ biến gồm hai bước: tạo SBOM (Software Bill of Materials — danh mục thành phần phần mềm) rồi quét các thành phần trong SBOM để tìm lỗ hổng đã biết.
Công cụ syft và grype sẽ báo cáo hai lỗ hổng GO-2026-5970 và GO-2026-6629 trong thư viện trên. Tuy nhiên, nếu chịu khó đào sâu, ta thấy cả hai đều không thực sự ảnh hưởng đến chương trình: lỗ hổng thứ nhất chỉ tồn tại trong gói unicode/norm, lỗ hổng thứ hai chỉ trong gói secure/precis — và chương trình của chúng ta không hề dùng đến chúng.
Cách tiếp cận dựa trên SBOM có hai vấn đề chí mạng:
- Quy trình thủ công này mở rộng theo kích thước codebase và số lượng dependency.
- Bạn phải lặp lại toàn bộ phân tích mỗi khi thay đổi code, vì rất có thể bạn sẽ bắt đầu dùng một hàm chứa lỗ hổng.
Phân tích khả năng tiếp cận: giải pháp cho ngôn ngữ lập trình
May mắn thay, các ngôn ngữ lập trình có cấu trúc chặt chẽ, nên việc suy luận về chúng trở nên dễ dàng với máy móc. Đội ngũ Go đặc biệt tận tâm trong công việc này: họ ghi lại mọi đường dẫn import và symbol bị ảnh hưởng bằng trường ecosystem_specific mỗi khi một lỗ hổng mới được ghi nhận.
Đây chính là cơ chế vận hành của govulncheck. Công cụ này dùng phân tích tĩnh mã nguồn kết hợp cơ sở dữ liệu lỗ hổng Go để thu hẹp báo cáo, chỉ giữ lại những lỗ hổng có thể ảnh hưởng thực sự đến ứng dụng. Với chương trình mẫu của chúng ta, nó kết luận: không tìm thấy lỗ hổng nào. Nếu có sức mạnh này, bạn thậm chí có thể tắt Dependabot và chỉ vá khi thực sự bị ảnh hưởng.
Nhưng cách này sụp đổ với hệ điều hành
Khi thử áp dụng tư duy tương tự cho một hệ điều hành, mọi thứ trở nên phức tạp. Với một Dockerfile dựa trên Debian và cài openssh-server, công cụ quét trả về tới 284 kết quả khớp lỗ hổng: 3 nghiêm trọng, 65 cao, 80 trung bình, 39 thấp và 97 không đáng kể.
Hãy lấy một CVE điển hình để phân tích: CVE-2007-2768. Về cơ bản, nếu sshd sử dụng mật khẩu dùng một lần OPIE thông qua PAM, kẻ tấn công có thể biết từ dấu nhắc đăng nhập liệu một tên người dùng có tồn tại hay không. Lỗ hổng này đã tồn tại từ năm 2007 mà không được vá ở thượng nguồn.
Kiểm tra thủ công cấu hình sshd, ta thấy PAM được bật nhưng xác thực tương tác bàn phím bị tắt — và đó là cách duy nhất sshd trao dấu nhắc đăng nhập cho PAM. Hơn nữa, không có module nào tên opie được cấu hình. Vậy là lỗ hổng không ảnh hưởng đến hệ thống này.
Vấn đề nằm ở chỗ: làm thủ công như vậy cho 283 lỗ hổng còn lại, lặp lại mỗi khi cấu hình thay đổi, là điều hoàn toàn bất khả thi.
Đây chính là điểm mấu chốt: quy trình dựa trên SBOM chỉ cho bạn biết phần mềm nào đang hiện diện, chứ không cho bạn biết phần mềm đó có thực sự gây ra rủi ro hay không.
Sức mạnh phi lý của NixOS
Điều gì khiến NixOS khác biệt? Xét một cấu hình hệ thống gần tương đương với ví dụ Docker ở trên, nhưng được viết bằng ngôn ngữ cấu hình của Nix. Với một flake khai báo nixosConfigurations.sshd, ta có thể thay syft bằng sbomnix và chạy đúng quy trình cũ.
Kết quả quét cho ra 272 kết quả khớp lỗ hổng — trong đó CVE-2007-2768 xuất hiện trên gói openssh phiên bản 10.5p1. Nhưng đây mới là phần thưởng thực sự: vì NixOS cho phép hệ thống hóa các điều kiện, ta có thể biểu diễn chính xác lý do lỗ hổng này không ảnh hưởng đến hệ thống.
Cụ thể, ta định nghĩa một biểu thức notAffected — đúng khi gói opie không tồn tại, khi xác thực tương tác bàn phím bị tắt, và khi không có rule PAM nào bật module chứa chuỗi opie. Từ đó, ta có thể tạo tài liệu VEX một cách có điều kiện, chỉ giữ lại tuyên bố khi các điều kiện vẫn còn đúng.
let
notAffected =
!(pkgs ? opie)
&& config.services.openssh.settings.KbdInteractiveAuthentication == false
&& !(lib.any (rule: rule.enable && lib.hasInfix "opie" rule.modulePath) (
lib.attrValues config.security.pam.services.sshd.rules.auth
));
in
{
system.build.vex = pkgs.writeText "vex.json" (
builtins.toJSON {
"@context" = "https://openvex.dev/ns/v0.2.0";
"@id" = "https://kammel.dev/vex/sshd";
author = "Fabian Kammel";
timestamp = "2026-10-11T00:00:00Z";
version = 1;
statements = lib.optional notAffected {
vulnerability.name = "CVE-2007-2768";
products = [ { "@id" = "pkg:nix/openssh"; } ];
status = "not_affected";
justification = "vulnerable_code_not_present";
};
}
);
}
Tích hợp vào quy trình quét, lỗ hổng đã được phân loại giờ đây tự động bị bỏ qua: số kết quả khớp giảm từ 272 xuống 271, với đúng 1 mục được đánh dấu ignored.
nixos-vex: Chia sẻ quy trình với cộng đồng
Điểm mấu chốt là: xây dựng các điều kiện này tốn rất nhiều công sức, nhưng phần thưởng là khổng lồ. Một khi CVE đã được phân loại và hệ thống hóa, chi phí kiểm tra lại gần như bằng không — chỉ tốn chút chi phí CI.
Tác giả bài viết đã áp dụng quy trình này cho các máy NixOS của mình và mã nguồn mở nó dưới dạng dự án nixos-vex, kèm các bản demo cho profile desktop và server. Mục tiêu không chỉ là chia sẻ quy trình, mà còn mời gọi phản hồi và hy vọng có thể đóng góp trở lại hệ sinh thái Nix.
Lưu ý quan trọng: Tác giả khuyến cáo chưa nên dùng nixos-vex như một nguồn dữ liệu có độ tin cậy cao ở giai đoạn hiện tại.
Đối với độc giả Việt Nam đang vận hành hệ thống Linux quy mô lớn, câu chuyện này mang lại bài học đáng giá: tự động hóa việc phân loại lỗ hổng dựa trên ngữ cảnh cấu hình thực tế — thay vì chỉ dựa vào danh sách thành phần phần mềm — có thể giảm mạnh gánh nặng cho đội bảo mật. Dù bạn dùng NixOS hay không, triết lý của VEX vẫn đáng để áp dụng: đừng chỉ hỏi "phần mềm này có lỗ hổng không?", mà hãy hỏi "lỗ hổng đó có thực sự chạm tới hệ thống của tôi không?".
Bài viết liên quan

Công nghệ
Suy giảm nhận thức hay sự tỉnh táo tăng lên? Góc nhìn từ làn sóng AI
11 tháng 10, 2026

Công nghệ
New York áp dụng quy định "Click to Cancel": đăng ký một cú nhấp, hủy cũng phải một cú nhấp
11 tháng 10, 2026

Công nghệ
Total Annihilation được tái sinh cho máy tính hiện đại với engine mã nguồn mở Nanolathe
11 tháng 10, 2026