Chúng tôi đã xây dựng một Trình bảo vệ mã nguồn tự hành chỉ trong một cuối tuần

Chúng tôi tham gia JacHacks với một mục tiêu táo bạo.

Xây dựng một công cụ theo dõi một kho lưu trữ (repository). Nó phải phát hiện được các thay đổi phụ thuộc (dependency) đáng ngờ. Nó phải chạy các phụ thuộc đó trong một môi trường sandbox để chứng minh chúng độc hại. Sau đó, nó phải viết một bản sửa lỗi và mở một pull request. Không có sự can thiệp của con người cho đến bước cuối cùng.

Chúng tôi gọi nó là GhostWatch. Nó đã giành giải Nhì trong hạng mục agentic.

Dưới đây là cách chúng tôi đã xây dựng nó và những gì chúng tôi đã học được.

Vấn đề

Các quy trình kiểm duyệt mã nguồn (code review) tiêu chuẩn có hai nhược điểm lớn:

  • Các công cụ không thể thấy được phạm vi ảnh hưởng (blast radius). Một thay đổi trong một hàm có thể làm hỏng các tệp ở rất xa. Hầu hết các công cụ không xem xét các mối liên kết.
  • Các cuộc tấn công chuỗi cung ứng (supply chain attacks) vượt qua các bước kiểm duyệt. Kẻ tấn công có thể đẩy một phiên bản bị nhiễm độc trực tiếp lên một registry. Không có pull request nào để kiểm duyệt. Bạn chỉ nhận ra sau khi thiệt hại đã xảy ra.

Giải pháp của chúng tôi

Chúng tôi đã xây dựng một hệ thống có khả năng nhận thức không gian. Chúng tôi đã sử dụng Jac để mô hình hóa mã nguồn dưới dạng một đồ thị (graph).

Trong đồ thị này:

  • Các tệp là các nút (nodes).
  • Các lệnh import là các cạnh (edges).

Để tìm phạm vi ảnh hưởng, chúng tôi không đoán mò. Chúng tôi thực hiện một bước duyệt đồ thị (graph walk). Điều này giúp logic bảo mật trở nên mang tính xác định (deterministic) và có thể giải thích được.

Công nghệ sử dụng (Tech Stack)

Chúng tôi đã sử dụng Jac thay vì Python thuần và các lệnh gọi LLM thủ công. Điều này đã thay đổi cách chúng tôi làm việc:

  • Mã nguồn chính là cấu trúc dữ liệu.
  • Tính bền vững (persistence) được tích hợp sẵn. Đồ thị repo của chúng tôi vẫn tồn tại sau khi khởi động lại mà không cần một cơ sở dữ liệu riêng biệt.
  • Việc tích hợp LLM diễn ra liền mạch. Chúng tôi chỉ sử dụng một từ khóa duy nhất để biến một hàm thành một lệnh gọi LLM trả về các đối tượng có kiểu dữ liệu (typed objects).

Những phần khó khăn

Không hề dễ dàng. Chúng tôi đã đối mặt với nhiều trở ngại:

  • Cú pháp mới: Jac sử dụng dấu chấm phẩy, dấu ngoặc nhọn và các từ khóa cụ thể như has thay vì self của Python. Chúng tôi đã dành vài giờ đầu tiên để sửa các lỗi phân tích cú pháp (parse errors).
  • Cạm bẫy React: Tôi đã cố gắng thay đổi trực tiếp (mutate) các danh sách tại chỗ. Điều này khiến frontend không cập nhật. Tôi đã phải chuyển sang gán lại các danh sách để kích hoạt việc render lại (re-renders).
  • Thiếu sót về tài liệu: Việc thiết lập môi trường mất nhiều thời gian hơn dự kiến vì một số tài liệu còn sơ sài.

Tại sao điều này lại quan trọng

Hầu hết các hệ thống agent yêu cầu bạn phải quản lý trạng thái (state), sự điều phối (orchestration) và tuần tự hóa (serialization) một cách thủ công. Với Jac, đồ thị là một cấu trúc ngôn ngữ. Kiến trúc hệ thống khớp hoàn toàn với vấn đề mà chúng tôi đang giải quyết.

Dự án này không hoàn hảo. Môi trường sandbox sử dụng các tiến trình con (subprocesses) cục bộ thay vì các microVM đám mây. Chúng tôi để lộ những khoảng trống này vì sự hoàn thiện trong một cuộc thi hackathon không nên là một lời nói dối.

Xem bản demo: https://www.youtube.com/watch?v=ZN0UVnNUpRs

Kiểm tra mã nguồn: https://github.com/ayushmk7/GhostWatch

Nguồn: https://dev.to/ayushmk/we-built-an-autonomous-code-guardian-in-a-weekend-heres-what-happened-4982

Cộng đồng học tập tùy chọn: https://t.me/GyaanSetuAi