Fuzzing tự động bằng AI: GitHub Security Lab ra mắt Taskflow Agent

Phần mềm24 tháng 9, 2026·10 phút đọc

GitHub Security Lab giới thiệu Fuzzing Taskflow — pipeline fuzzing tự động cho các dự án C/C++, sử dụng LLM agent để viết harness, chạy AFL++, theo dõi độ phủ và phân loại lỗi mà không cần con người giám sát. Công cụ mã nguồn mở này hứa hẹn giúp các nhà phát triển tìm ra lỗ hổng bảo mật nhanh chóng hơn.

Fuzzing tự động bằng AI: GitHub Security Lab ra mắt Taskflow Agent

Trong nhiều năm, fuzzing (kỹ thuật kiểm thử tự động bằng cách "ném" dữ liệu ngẫu nhiên vào phần mềm để tìm lỗi) vẫn được xem là một trong những phương pháp hiệu quả nhất để phát hiện lỗ hổng bảo mật. Nhưng nó chưa bao giờ là giải pháp tự động hoàn toàn — luôn cần một con người túc trực để theo dõi độ phủ, viết harness mới và phân loại các sự cố. GitHub Security Lab vừa công bố Fuzzing Taskflow, một pipeline fuzzing tự động dựa trên AI, nhằm giải quyết chính điểm nghẽn đó.

Fuzzing vẫn cần con người — cho đến nay

Ngay cả những dự án đã tham gia OSS-Fuzz nhiều năm vẫn có thể ẩn chứa lỗi nghiêm trọng. Lý do gần như luôn giống nhau: ai đó phải liên tục theo dõi độ phủ, viết harness cho những phần mã chưa được chạm tới, và phân loại hàng loạt sự cố tràn bộ đệm hay treo chương trình. Nói cách khác, fuzzing vẫn cần một con người trong vòng lặp.

Câu hỏi mà kỹ sư Antonio Morales của GitHub Security Lab đặt ra: bao nhiêu phần công việc thủ công đó có thể giao cho một LLM agent? Câu trả lời chính là Fuzzing Taskflow — pipeline fuzzing tự động cho các dự án C/C++. Bạn chỉ cần trỏ nó vào một repository GitHub, phần còn lại agent sẽ tự lo: xác định điểm vào phù hợp, phân tích hệ thống build, viết harness, chạy AFL++, đọc báo cáo độ phủ, cải thiện harness, phân loại từng sự cố và viết báo cáo lỗ hổng cho mỗi lỗi duy nhất.

Giao diện GitHub Security Lab Taskflow Agent cho fuzzingGiao diện GitHub Security Lab Taskflow Agent cho fuzzing

Cách chạy Fuzzing Taskflow

Cách đơn giản nhất là truy cập kho mã nguồn mở GitHubSecurityLab/seclab-taskflows-fuzzing trên GitHub và khởi tạo một Codespace. Sau đó chạy script:

./scripts/fuzzing/run_fuzzing.sh PROJECT

Ví dụ với dự án nén dữ liệu phổ biến XZ Utils:

./scripts/fuzzing/run_fuzzing.sh tukaani-project/xz

Tham số truyền vào chỉ là slug owner/repo trên GitHub. Agent sẽ tự thực hiện mọi bước chuẩn bị: cài đặt công cụ như AFL, clone repository, xác định các hàm quan trọng nhất trong mã nguồn và tạo fuzz target cho những hàm đó.

Lưu ý an toàn quan trọng: Taskflow này chạy afl-fuzz, clang và các lệnh build tùy ý do LLM chọn trực tiếp trên máy chủ, không qua container. Một agent bị tấn công prompt injection về lý thuyết có thể làm bất cứ điều gì mà người dùng của bạn có thể làm. Vì vậy chỉ nên chạy trong môi trường dùng một lần như Codespace hoặc máy ảo tạm, và không cấp quyền cao.

Kiến trúc: tách biệt quyết định và thực thi

Fuzzing Taskflow được xây dựng trên GitHub Security Lab Taskflow Agent, framework viết tự động hóa bảo mật bằng LLM. Pipeline gồm ba lớp:

  • Shell driver (run_fuzzing.sh) nối các giai đoạn với nhau
  • Các tệp YAML taskflow, mỗi giai đoạn một tệp, đóng vai trò prompt hướng dẫn agent
  • Bộ công cụ MCP mà agent gọi để thực thi công việc thật: chạy AFL, biên dịch harness, lưu sự cố, đọc báo cáo độ phủ

Nguyên tắc thiết kế quan trọng nhất là tách biệt trách nhiệm rõ ràng: agent LLM nắm quyết định, công cụ MCP nắm thực thi. Agent quyết định fuzz cái gì, viết harness nào, đuổi theo khoảng trống độ phủ nào tiếp theo — nhưng không bao giờ gọi trực tiếp AFL hay clang. Toàn bộ trạng thái lưu trong cơ sở dữ liệu SQLite (fuzz_context.db), nên các giai đoạn không truyền dữ liệu qua bộ nhớ mà chỉ qua database.

Một chi tiết nhỏ nhưng quan trọng: mỗi harness được build hai lần. Bản .afl dùng để fuzz với instrumentation của AFL, còn bản .cov dùng để tạo báo cáo độ phủ dễ đọc cho con người.

Vòng lặp phản hồi độ phủ — trái tim của pipeline

Đây là phần tự động hóa trực tiếp quy trình thủ công mà bất kỳ nhà nghiên cứu bảo mật nào cũng từng trải qua. Thay vì tự tay đọc báo cáo LCOV để tìm nhánh chưa được phủ rồi viết harness mới, cả hai bước đều được giao cho agent.

Mỗi vòng lặp, với từng harness, agent chạy AFL trong một khoảng thời gian, phát lại hàng đợi trên bản .cov để có báo cáo độ phủ thật, rồi đọc danh sách nhánh chưa được chạm tới. Dựa trên những gì tìm thấy, nó chọn một trong các hành động:

  • Thêm seed mới được thiết kế để chạm tới nhánh chưa phủ
  • Sửa mã nguồn harness để gọi thêm API
  • Tự động làm giàu từ điển AFL bằng các hằng số magic mà guard đang so sánh
  • Bỏ qua nếu đó là nhánh lỗi hiếm gặp hoặc mã của bên thứ ba không đáng theo đuổi

Ngân sách thời gian tăng gấp đôi mỗi vòng: 30 giây → 60 → 120 → 240 → 480 → 960 giây (khoảng 32 phút cho mỗi target). Ý tưởng là dành những vòng ngắn, rẻ ở giai đoạn đầu khi còn nhiều độ phủ dễ lấy, và những vòng dài hơn về sau khi fuzzer cần thêm thời gian phá vỡ các guard khó.

Vòng lặp cũng có cơ chế phát hiện cao nguyên: khi hai vòng liên tiếp mỗi vòng tăng dưới 1% độ phủ dòng tuyệt đối, agent quyết định đã đạt điểm lợi ích giảm dần và chuyển sang mục tiêu khác, tránh đốt hàng giờ tính toán để vắt kiếm phần trăm cuối cùng.

Bảng theo dõi độ phủ và tiến trình fuzzing theo thời gian thựcBảng theo dõi độ phủ và tiến trình fuzzing theo thời gian thực

Fuzzing hiểu cấu trúc dữ liệu

Các mutator byte-level mặc định của AFL (đảo bit, cộng trừ, ghép khối) làm rất tốt với định dạng nhị phân nhưng gặp khó với đầu vào dạng văn bản có cấu trúc. Giải pháp cổ điển là tự viết custom mutator cho từng định dạng — công việc tẻ nhạt. Fuzzing Taskflow mang đến bốn cơ chế bổ trợ:

  1. Từ điển và custom mutator theo định dạng. Với các định dạng được nhận diện (JSON, XML, regex, PNG, TLV nhị phân), pipeline có sẵn từ điển AFL và tệp LLVMFuzzerCustomMutator bằng C. Mutator JSON biết ghép token và nhân bản dấu ngoặc cân bằng; mutator XML hiểu về tag, entity và token "billion laughs"; mutator regex mang theo các mẫu ReDoS thực tế.

  2. Từ điển ở mức mã nguồn. Với định dạng chưa nhận diện, pipeline tự tạo custom mutator bằng cách quét chính các tệp .c/.h của mục tiêu, trích xuất chuỗi ký tự và hằng số số 32-bit từ #define, case, enum. Trực giác rất đơn giản: những giá trị magic thú vị nhất mà parser kiểm tra thường được viết ở đâu đó ngay trong mã nguồn của nó.

  3. Từ điển AFL động, làm giàu theo độ phủ. Sau mỗi bước đo độ phủ, pipeline xem xét các guard gần những dòng chưa được phủ (strncmp, memcmp, case 0xN, == 'X') và bổ sung token mới. Từ điển thực sự lớn dần về phía đoạn mã mà fuzzer chưa chạm tới.

  4. Toán tử ghép corpus. Mutator thông minh có thể nạp tệp từ thư mục corpus và ghép các vùng ngẫu nhiên của chúng vào đầu vào — kiểu tái tổ hợp mà chế độ havoc mặc định của AFL làm chưa tốt.

Corpus tiến hóa — không bỏ phí tiến độ

Một trong những điều âm thầm giết chết hiệu quả fuzzing là vứt bỏ tiến độ. Nếu mỗi lần chạy đều bắt đầu từ seed gốc, bạn phải trả lại chi phí khám phá những đường dẫn cũ.

Để tránh điều đó, mỗi harness có một thư mục corpus ổn định tồn tại qua các vòng lặp và qua cả các chiến dịch. Cuối mỗi vòng, hàng đợi AFL được gộp vào thư mục này và chạy qua afl-cmin để giữ kích thước trong tầm kiểm soát. Kết quả là những đầu vào thú vị của hôm qua được mang sang lần chạy hôm nay — dừng rồi khởi động lại chiến dịch, bạn không mất gì cả.

Phân loại sự cố và báo cáo lỗ hổng

Tìm ra sự cố chỉ là một nửa công việc. Như bất kỳ ai từng phân tích nguyên nhân gốc rễ đều biết, phân loại thường là phần tẻ nhạt nhất — và đây là nơi khác mà agent tỏa sáng.

Sau khi vòng fuzzing kết thúc, ba giai đoạn chạy tự động. Thứ nhất, mỗi sự cố được tối giản bằng afl-tmin, phát lại dưới ASan để lấy stack trace, và loại trùng theo hash đỉnh stack. Thứ hai, các sự cố đã biết trước đó được phát lại trên binary hiện tại để xem bản vá thượng nguồn đã khắc phục chưa. Thứ ba, agent đọc mã nguồn harness và hàm gây lỗi, lần theo chuỗi gọi từ API công khai, rồi viết báo cáo Markdown cho từng sự cố.

Mỗi báo cáo gán một trong các kết luận: vulnerability (lỗ hổng thật), library_hardening, harness_bug (lỗi nằm ở harness chứ không phải thư viện), OOM, timeout, assertion_failure hoặc duplicate. Mỗi báo cáo bao gồm phân tích nguyên nhân gốc rễ kèm tham chiếu file:line, lập luận về khả năng tiếp cận, đánh giá khả năng khai thác, bản vá đề xuất dạng unified diff và bản nháp test hồi quy.

Các bản vá đề xuất được đánh dấu "cần xem xét" là có lý do. Phân tích của agent bị giới hạn bởi hiểu biết của mô hình về mã mục tiêu, và nó có sai sót. Hãy coi các kết luận này là điểm khởi đầu được chuẩn bị kỹ càng cho con người, không phải kết quả cuối cùng.

Bảng điều khiển trực tiếp

Chạy một chiến dịch tự động mà không nhìn thấy nó đang làm gì thì thật khó chịu, nên pipeline công bố mọi thứ lên một bảng điều khiển HTML trực tiếp, tự khởi động nền ở cổng 8765 ngay khi bạn chạy chiến dịch. Trong Codespace, cổng này được tự động chuyển tiếp, nên bạn có thể mở trên bất kỳ trình duyệt nào và theo dõi tiến độ theo thời gian thực.

Bảng điều khiển HTML theo dõi chiến dịch fuzzingBảng điều khiển HTML theo dõi chiến dịch fuzzing

Trang hiển thị nhịp "đang chạy" theo từng harness, bảng xu hướng độ phủ kèm sparkline, bản đồ nhiệt sự cố và dòng thời gian các vòng lặp.

Ý nghĩa với cộng đồng phát triển phần mềm

Với các nhà phát triển và bảo trì dự án C/C++ — đặc biệt là các thư viện mã nguồn mở phổ biến tại Việt Nam như xử lý ảnh, nén dữ liệu, parser định dạng tệp — Fuzzing Taskflow là một cách tiếp cận đáng thử. Nếu dự án của bạn chưa từng được fuzz, công cụ này giúp khởi động nhanh chóng. Nếu đã fuzz rồi, nó có thể giúp tìm lỗi mới bằng cách tăng độ phủ.

Điều đáng chú ý là triết lý thiết kế: không thay thế con người bằng AI một cách mù quáng, mà đẩy điểm nghẽn về phía trước bằng cách giao phần lặp đi lặp lại cho agent, trong khi giữ ranh giới rõ ràng giữa phán đoán của agent và công cụ thực thi công việc thật.

Mã nguồn mở, hoan nghênh đóng góp và báo lỗi qua issue trên repository của GitHub Security Lab.

Chia sẻ:FacebookX
Nội dung tổng hợp bằng AI, mang tính tham khảo. Xem bài gốc ↗