Bỏ qua nội dung chính
OpenAI

13 tháng 5, 2026

Kỹ thuậtBảo mật

Xây dựng sandbox an toàn, hiệu quả để hỗ trợ Codex trên Windows

Tác giả: David Wiesen, Thành viên Ban Kỹ thuật

Đang tải…

Khi tôi gia nhập nhóm kỹ thuật Codex vào tháng 9 năm 2025, Codex trên Windows chưa có cơ chế sandbox, nghĩa là người dùng Windows buộc phải chọn giữa hai phương án kém khi dùng các tác nhân lập trình của OpenAI:

  1. Phê duyệt gần như mọi lệnh (kể cả lệnh đọc) mà một tác nhân lập trình muốn chạy, điều này kém hiệu quả và khá phiền. Một lợi ích lớn của việc sử dụng Codex là bạn không phải tự mình làm tất cả những công việc tẻ nhạt.
  2. Bật chế độ Truy cập hoàn toàn: cho phép Codex chạy mọi lệnh mà không cần phê duyệt hay bị hạn chế, giúp giảm cản trở nhưng đánh đổi bằng việc mất đi khả năng giám sát.

Codex, tác nhân lập trình của chúng tôi, chạy trên laptop của nhà phát triển—dù là qua CLI, tiện ích mở rộng IDE hay ứng dụng máy tính. Nó quản lý cuộc trò chuyện giữa một người đang thao tác trên bàn phím và một mô hình chạy trên đám mây để thực hiện suy luận.

Theo mặc định, Codex chạy với quyền của một người dùng thực, nghĩa là nó có thể làm mọi thứ mà người dùng đó có thể làm. Tính năng này rất mạnh mẽ nhưng cũng tiềm ẩn nguy hiểm. Mô hình lập trình có thể yêu cầu hệ thống điều khiển chạy lệnh cục bộ, từ chạy kiểm thử đến đọc hoặc chỉnh sửa tệp hay tạo nhánh Git, vì vậy chế độ mặc định của Codex cố gắng cân bằng giữa hiệu quả và an toàn một cách phù hợp. Chế độ mặc định này cho phép Codex đọc tệp gần như ở mọi nơi và ghi tệp trong không gian làm việc của bạn (tức là thư mục hệ thống nơi bạn đang chạy Codex), đồng thời không có quyền truy cập mạng trừ khi bạn nói rõ bạn muốn như vậy. Để tự động giới hạn việc ghi tệp và truy cập mạng trong phạm vi an toàn này, Codex cần một môi trường sandbox thực sự thực thi nghiêm ngặt được các ràng buộc đó.

Sandbox là một môi trường thực thi bị giới hạn. Khi một nhà phát triển sử dụng Codex, hệ điều hành của máy tính họ sẽ khởi chạy một lệnh với quyền hạn bị hạn chế, và những hạn chế đó sẽ lan truyền xuống cây tiến trình. Mọi lệnh Codex đều được chạy trong môi trường biệt lập ngay từ đầu, và mọi tiến trình con cháu của nó đều nằm trong cùng một ranh giới đó.

Sơ đồ hiển thị các ranh giới cô lập của hệ điều hành trong sandbox Codex.

Codex cần các tính năng cô lập (isolation) do hệ điều hành của máy tính thực thi để triển khai một sandbox hiệu quả. Một số hệ điều hành có sẵn các tiện ích làm việc này khá tốt (ví dụ: Seatbelt trên MacOs, seccomp hoặc bubblewrap trên Linux); tuy nhiên, hiện tại Windows không cung cấp sẵn loại khả năng này.

Để khiến Codex trên Windows an toàn và dễ dùng như ở mọi nơi khác, chúng tôi cần tự triển khai sandbox của riêng mình.

Những điểm chưa đáp ứng của các công cụ Windows hiện có

Windows có một số công cụ và cơ chế nền tảng cho việc cô lập. Dù không cái nào thực sự đáp ứng yêu cầu của chúng tôi, chúng tôi vẫn xem xét một số giải pháp tiềm năng—cụ thể là AppContainer, Windows Sandbox và nhãn Mandatory Integrity Control.

AppContainer

  • Khái niệm: AppContainer là sandbox gốc của Windows, một mô hình cô lập dựa trên năng lực được xây dựng cho các ứng dụng biết trước chính xác chúng cần truy cập gì.
  • Vì sao nên: Là giải pháp hấp dẫn vì cung cấp một ranh giới hệ điều hành thực sự thay vì các hạn chế theo kiểu nỗ lực tối đa.
  • Tại sao không: Codex không phải là một ứng dụng có phạm vi được giới hạn chặt chẽ. Nó thúc đẩy các quy trình làm việc mở của nhà phát triển: shell, Git, Python, trình quản lý gói, công cụ xây dựng và bất kỳ tập tin nhị phân nào khác mà tác nhân quyết định là cần thiết. Trên thực tế, điều đó khiến AppContainer trở thành một hình dạng không phù hợp với vấn đề. Đó là sự cô lập mạnh mẽ, nhưng chỉ áp dụng cho một nhóm khối lượng công việc hẹp hơn nhiều so với việc "cho phép một tác nhân hoạt động như một nhà phát triển".

Sandbox Windows

  • Khái niệm: Windows Sandbox là máy ảo nhẹ, dùng một lần của Microsoft. Bạn có một màn hình nền Windows mới với ranh giới cô lập mạnh, và mọi thứ bạn làm bên trong sẽ biến mất khi phiên kết thúc.
  • Vì sao nên: Hấp dẫn vì những lý do hiển nhiên—tương thích với phần mềm tùy ý tốt hơn nhiều so với AppContainer, và xét về bảo mật thì đây là một “hộp” mạnh hơn hẳn.
  • Vì sao không nên: Codex cần tác động trực tiếp trên checkout thực tế, công cụ và môi trường của người dùng, chứ không phải bên trong một máy dùng một lần riêng biệt cần thiết lập và cầu nối giữa máy chủ và máy khách. Nó cũng gặp một vấn đề cơ bản về sản phẩm: Windows Sandbox thậm chí còn không khả dụng trên các SKU Windows Home.

Gắn nhãn toàn vẹn Kiểm soát bắt buộc với tính toàn vẹn (MIC)

  • Khái niệm: Windows có một khái niệm gọi là “mức độ toàn vẹn”, chẳng hạn như thấp, trung bình và cao, để xác định mức độ tin tưởng của hệ thống đối với các đối tượng và tiến trình. Nguyên tắc cơ bản là một tiến trình có mức độ toàn vẹn thấp hơn không thể ghi vào một đối tượng có mức độ toàn vẹn cao hơn, ngay cả khi ACL thông thường cho phép điều đó. Ví dụ, một tiến trình có tính toàn vẹn thấp được coi là kém tin cậy hơn, vì vậy Windows sẽ chặn nó ghi vào các đối tượng có tính toàn vẹn trung bình thông thường, trừ khi các đối tượng đó được gắn nhãn lại một cách rõ ràng để cho phép điều đó.
  • Lý do: Trên lý thuyết, MIC trông rất thanh nhã—chạy Codex ở mức toàn vẹn thấp, gắn nhãn lại các gốc có thể ghi thành toàn vẹn thấp và để Windows thực thi việc cấm ghi ở mọi nơi khác. Điều đó lẽ ra đã cung cấp cho chúng ta một hướng không cần quyền admin, với một cơ chế thực sự của hệ điều hành hỗ trợ phía sau.
  • Tại sao không: Giống như ACL, nhãn toàn vẹn sửa đổi hệ thống tệp thực của máy chủ, và trong trường hợp này, sự thay đổi về mặt ngữ nghĩa là đặc biệt rộng. Việc đánh dấu một không gian làm việc là có tính toàn vẹn thấp không chỉ có nghĩa là "Codex có thể ghi vào đây." Điều đó có nghĩa là các tiến trình có mức toàn vẹn thấp nói chung có thể ghi vào đó. Trên một máy phát triển thực tế, điều đó biến bản checkout thực tế của người dùng thành một điểm nhận có mức toàn vẹn thấp cho host, điều này rủi ro hơn nhiều so với việc cấp các ACL có phạm vi được nhắm mục tiêu cẩn thận cho một thiết kế sandbox. Ngay cả khi các công cụ phát triển có độ tin cậy trung bình tiếp tục hoạt động, mô hình tin cậy cơ bản của không gian làm việc đã thay đổi theo cách khó kiểm soát và khó biện minh hơn.

Sau khi đánh giá tất cả các lựa chọn và thấy chúng đều không khả thi, chúng tôi bắt đầu thiết kế giải pháp riêng để mang lại trải nghiệm Codex tốt cho người dùng Windows.

Bản nguyên mẫu đầu tiên: “sandbox không nâng quyền”

Nguyên mẫu hoạt động đầu tiên của chúng tôi đã sử dụng sự kết hợp giữa các khái niệm và công cụ của Windows để thực hiện việc cách ly cần thiết. Ngay từ đầu, một mục tiêu là làm cho điều này hoạt động mà không cần quyền quản trị, nghĩa là Codex sẽ không cần câu lệnh người dùng cấp quyền quản trị chỉ để thiết lập hoặc chạy môi trường thử nghiệm. Điều đó có nghĩa là phải tìm ra cách đặt ra những giới hạn hợp lý cho hai việc: ghi tệp và truy cập mạng.

Giới hạn việc ghi tệp

Nếu không đặt chút giới hạn ghi tệp nào, chúng tôi sẽ gặp vấn đề bảo mật. Nếu giới hạn quá mức, sandbox sẽ làm giảm năng suất của người dùng vì phải liên tục xin phê duyệt. Để giải quyết bài toán này, chúng tôi dựa vào hai thành phần nền tảng quan trọng của Windows: SID và token hạn chế ghi.

SID cho phép chúng tôi cấp cho sandbox một danh tính

SID, hay mã định danh bảo mật, là định danh mà Windows liên kết với các quyền truy cập. Mỗi người dùng có một SID, các nhóm có SID, và ngay cả một phiên đăng nhập riêng lẻ cũng có SID riêng. Ví dụ: một phiên đăng nhập hiện tại có thể có SID như S-1-5-5-X-Y. SID được gán cho nhóm quản trị viên cục bộ có thể là S-1-5-32-544.

Windows cũng cho phép bạn tạo SID tổng hợp không tương ứng với người dùng thực nào nhưng vẫn có thể xuất hiện trong ACL (danh sách kiểm soát truy cập), vốn định nghĩa ai có thể đọc/ghi/thực thi các tệp hoặc thư mục hệ thống cụ thể. Điều đó biến SID thành cơ chế nền tảng hữu ích cho sandbox của chúng tôi: chúng tôi có thể tạo các SID chỉ dành riêng để cho sandbox Codex sử dụng mà không ảnh hưởng đến bất kỳ thứ gì khác trên máy.

Token hạn chế ghi giới hạn nơi Codex có thể sửa đổi tệp

Token tiến trình là các đối tượng bảo mật trong Windows xác định danh tính và đặc quyền cho một tiến trình đang chạy. Chúng xác định những hành động mà một tiến trình có thể thực hiện. Token bị hạn chế ghi là một loại token tiến trình cụ thể khiến Windows thực hiện thêm một bước kiểm tra quyền truy cập đối với các thao tác ghi.

Để một thao tác ghi thành công, phải vượt qua hai lần kiểm tra:

  1. Danh tính người dùng thông thường (chủ sở hữu token) phải được phép thực hiện việc đó
  2. Ít nhất một SID trong danh sách SID bị hạn chế của token cũng phải được cấp quyền truy cập
Sơ đồ có tiêu đề Việc ghi trong sandbox yêu cầu cả quyền truy cập người dùng thông thường và quyền truy cập SID sandbox-write.

Thực tế, nhờ những kiểm tra này, chúng tôi có thể sử dụng ACLs để định nghĩa chính xác những nơi sandbox được phép sửa đổi trên hệ thống tệp, từ đó mang lại mức độ chi tiết mà chúng tôi cần cho các thao tác ghi..

Với SID và token hạn chế ghi, sandbox không nâng quyền của chúng tôi hoạt động như sau:

  1. Quá trình thiết lập sandbox tạo một SID tổng hợp có tên sandbox-write.
  2. SID sandbox-write đã được cấp quyền ghi, thực thi và xóa đối với
    1. Thư mục làm việc hiện tại
    2. Mọi writable_roots bổ sung được cấu hình trong config.toml.
  3. Quá trình thiết lập sandbox từ chối rõ ràng quyền ghi của chính SID đó đối với các vị trí “chỉ đọc trong vùng có thể ghi” như:
    1. <cwd>/.git
    2. <cwd>/.codex
    3. <cwd>/.agents
  4. Codex khởi chạy các lệnh dưới một token hạn chế ghi mà danh sách SID bị hạn chế bao gồm Everyone, SID của phiên đăng nhập hiện tại và SID tổng hợp sandbox-write.

Về cơ bản, quy trình này đã giải quyết hiệu quả việc hạn chế ghi tệp và trông rất triển vọng. Giờ chúng tôi cần một giải pháp để giới hạn quyền truy cập mạng của sandbox.

Giới hạn quyền truy cập mạng

Giới hạn quyền truy cập mạng là một phần quan trọng của sandbox; nếu không có nó, mã độc có thể lấy dữ liệu từ máy và đưa lên mạng internet. Vì muốn tránh yêu cầu nâng quyền, nên chúng tôi có ít lựa chọn để chặn mạnh mẽ lưu lượng mạng. Các công cụ chúng tôi muốn dùng, như Windows Firewall, nói chung không thể cài đặt nếu không có quyền quản trị.

Do không có tùy chọn sử dụng Windows Firewall, chúng tôi đã hạn chế được những gì mình có thể kiểm soát. Chúng tôi đã cố gắng làm cho môi trường con theo cơ chế fail-closed (đóng khi lỗi) đối với các loại công cụ có kết nối mạng mà các nhà phát triển thực sự sử dụng, để các lệnh Git, trình cài đặt gói, v.v. sẽ thất bại trong môi trường sandbox và người dùng sẽ phải phê duyệt mọi thao tác hướng ra Internet. Ý tưởng là vô hiệu hóa các lối thoát hiển nhiên: gửi lưu lượng có nhận biết proxy đến một điểm cuối không hoạt động, khiến cơ chế truyền tải HTTP(S) của Git làm điều tương tự, và khiến Git qua SSH thất bại ngay lập tức. Thêm vào đó, chúng tôi đã thêm một thư mục denybin nhỏ vào PATH và sắp xếp lại PATHEXT để các tập lệnh SSH và SCP giả lập được giải quyết trước các tập lệnh nhị phân thực sự.

Ví dụ, đây là một số ghi đè môi trường cụ thể mà chúng tôi dùng để giới hạn quyền truy cập mạng:

  • HTTPS_PROXY=http://127.0.0.1:9
  • ALL_PROXY=http://127.0.0.1:9
  • GIT_HTTPS_PROXY=http://127.0.0.1:9
  • NO_PROXY=máy chủ cục bộ,127.0.0.1,::1
  • GIT_SSH_COMMAND=cmd /c exit 1
Sơ đồ hiển thị kiến trúc sandbox nâng quyền với các quy tắc tường lửa và một người dùng Windows chuyên dụng.

Cách đó chặn được khá nhiều lưu lượng thông thường do công cụ tạo ra, nhưng vẫn chỉ mang tính khuyến nghị. Một tiến trình có thể bỏ qua môi trường, bỏ qua PATH, hoặc просто mở socket trực tiếp—quá rủi ro.

Cách tiếp cận không nâng quyền đi cùng sự đánh đổi

Cũng như bất kỳ quá trình triển khai phần mềm thú vị nào, nguyên mẫu đầu tiên đều có những ưu và nhược điểm. Dù nó hoàn thành nhiệm vụ chỉ với vài tính năng Windows tiêu chuẩn, cho phép ghi trên hệ thống tệp rất rõ ràng và chi tiết, đồng thời chạy không cần nâng quyền—giúp giảm nhu cầu người dùng phải chấp nhận quá nhiều câu lệnh nâng quyền hoặc phải là quản trị viên trên máy cục bộ—nhưng phương án này có một số nhược điểm thực sự, trong đó có những nhược điểm khiến nó không đủ điều kiện trở thành thiết kế cuối cùng của chúng tôi:

  • Tốc độ thiết lập: Việc áp dụng ACL cho không gian làm việc có thể tốn kém tùy theo cấu trúc thư mục (topology) của không gian làm việc.
  • Dấu vết: Chúng tôi áp dụng ACL thực lên hệ thống của nhà phát triển, dù dấu vết này không quá xâm lấn vì mọi ACL được áp dụng đều liên quan đến một SID tổng hợp tùy chỉnh chỉ được sandbox sử dụng.
  • Ngữ nghĩa khó thay đổi: Việc phụ thuộc vào các ACL (danh sách kiểm soát truy cập) cho các hạn chế dựa trên tệp có nghĩa là việc thay đổi ngữ nghĩa của sandbox sẽ tốn kém và phức tạp. Trong khi đó, trên macOS, chúng ta có thể thay đổi linh hoạt cách tạo .sbpl tệp dùng để cấu hình Seatbelt, sandbox Windows có thể yêu cầu một thao tác chậm và tốn nhiều tài nguyên để điều chỉnh ACL.
  • Khả năng bảo vệ mạng yếu. Như đã nói ở trên, nó chỉ mang tính “khuyến nghị”, chắc chắn sẽ bị một số chương trình dùng stack mạng riêng vượt qua và không được thiết kế để chống chọi với mã đối kháng.

Ba vấn đề đầu tiên vốn là đặc tính cố hữu của một triển khai sandbox tùy chỉnh đủ linh hoạt cho quy trình tác nhân. Tuy nhiên, việc triệt tiêu mạng thì lại là câu chuyện khác.

Triệt tiêu mạng là điều quá quan trọng

Ngoài việc một tác nhân độc hại có thể dễ dàng vượt qua cơ chế triệt tiêu mạng dựa trên môi trường, rất nhiều mã/tệp nhị phân với mục đích tốt cũng sẽ vượt qua chỉ đơn giản vì chúng không tuân theo các biến proxy môi trường, hoặc vì chúng tự triển khai mã mạng dựa trên socket. Chúng tôi cảm thấy riêng khía cạnh này đã đủ để cân nhắc đầu tư vào một chế độ sandbox tốt hơn.

Để có khả năng triệt tiêu mạng tốt hơn, chúng tôi muốn dùng Windows Firewall, công cụ cho phép chặn lưu lượng mạng đi ra theo người dùng hoặc chương trình. Đáng tiếc là chúng tôi không thể tạo hiệu quả một quy tắc tường lửa chức năng chỉ áp dụng cho các lệnh do harness Codex sinh ra, vì một vài lý do:

  • Windows không cho phép khớp quy tắc tường lửa với danh tính không chính của mã thông báo bị hạn chế. Điều này có nghĩa là chúng tôi không thể áp dụng quy tắc tường lửa cho “bất kỳ token nào có chứa SID tổng hợp của chúng tôi trong danh sách SID bị hạn chế.”
  • Dù chúng tôi có thể tạo một quy tắc tường lửa khớp với một tệp nhị phân cụ thể, điều đó chỉ cho phép giới hạn mạng đối với chính codex.exe. Điều này sẽ không áp dụng cho các tiến trình mà tác tử khởi chạy thay mặt người dùng, chẳng hạn như các tiến trình Git hoặc Python.
  • Các chiều đối sánh khác của tường lửa cũng có cấu trúc không đúng. Các quy tắc giới hạn phạm vi người dùng vẫn khớp với người dùng Windows thực sự trong thiết kế không có quyền quản trị, chứ không chỉ là người dùng con bị hạn chế. Các quy tắc đường dẫn chương trình quá chung chung: chúng có thể chặn codex.exe hoặc python.exe nói chung, nhưng không thể chặn riêng trường hợp gọi python.exe trong môi trường sandbox này. Các quy tắc dựa trên cổng hoặc địa chỉ cũng hoàn toàn là một chính sách sai lầm. Chẳng hạn, chúng tôi không muốn chặn cổng 443; chúng tôi muốn chặn quyền truy cập ra ngoài tùy ý từ cây tiến trình bị hạn chế cụ thể này.

Để áp dụng một quy tắc tường lửa dành riêng cho các lệnh trong sandbox, chúng tôi cần chạy chúng dưới một principal riêng biệt, chứ không phải người dùng “thực”. Cách tiếp cận này dẫn chúng tôi sang một hướng mới, trong đó chúng tôi nới lỏng ràng buộc “không nâng quyền”.

Thiết kế lại: “sandbox nâng quyền”

Phiên bản lặp tiếp theo của môi trường sandbox, tức là phần triển khai hiện tại của chúng tôi, yêu cầu quyền quản trị viên nâng cao trong quá trình thiết lập. Do đó, tôi gọi nó là “sandbox nâng cao.” Tại ranh giới nơi Codex tạo ra một lệnh trên hệ thống, môi trường sandbox được nâng cao trông giống như môi trường sandbox không được nâng cao. Nó vẫn chạy các quy trình con dưới một token bị hạn chế — tương tự như một write_restricted token có cùng danh sách [Everyone, Logon, Synthetic]SID bị hạn chế — tuy nhiên, chính của token này không còn là người dùng Windows thực tế nữa mà là một trong hai người dùng cục bộ do chính Codex tạo ra:

  • CodexSandboxOffline (người dùng bị các quy tắc tường lửa hướng đến)
  • CodexSandboxOnline (người dùng không bị các quy tắc tường lửa hướng đến)

Chi tiết có vẻ nhỏ này thực ra lại có ý nghĩa lớn đối với sandbox, ai có thể sử dụng nó, cũng như độ phức tạp của quá trình thiết lập và thực thi lúc chạy.

Sơ đồ hiển thị các ghi đè môi trường mạng cho sandbox không nâng quyền.

Nhìn bên ngoài, nó tương tự nguyên mẫu không nâng quyền, kèm theo các quy tắc tường lửa và một người dùng Windows chuyên dụng, là thành phần thực sự chạy các lệnh. (Tuy nhiên, việc đưa vào các khái niệm mới này cũng đồng nghĩa có nhiều công việc thiết lập hơn cần làm trước khi sandbox có thể bắt đầu chạy và bảo vệ các lệnh.)

Giờ chúng tôi cần một bước thiết lập chính thức

Thiết kế sandbox không nâng quyền có bước thiết lập đơn giản, nhưng tương đối nhỏ:

  • Tạo SID tổng hợp nếu cần
  • Áp dụng ACL cho SID tổng hợp sandbox-write

Tuy nhiên, có nhiều việc phải làm với sandbox nâng quyền hơn.

  • Tạo SID tổng hợp, nếu chưa có
  • Tạo người dùng sandbox trực tuyến và không trực tuyến, nếu chưa được tạo
  • Lưu cục bộ thông tin xác thực của các người dùng mới tạo và mã hóa bằng Windows Data Protection API (DPAPI) ở nơi mà các người dùng sandbox thực sự không thể đọc
  • Tạo các quy tắc tường lửa chặn tất cả truy cập mạng ra ngoài của tài khoản CodexSandboxOffline hoặc, nếu các quy tắc đó đã tồn tại, hãy kiểm tra rằng chúng chính xác

Có một điểm phức tạp nữa trong giai đoạn thiết lập. Môi trường thử nghiệm của Codex dự kiến sẽ có quyền truy cập đọc tương đương với người dùng Windows thực tế. Trong môi trường thử nghiệm không có quyền quản trị, nơi SID chính của token bị hạn chế là người dùng Windows, điều này đã được thực hiện. Tuy nhiên, điều đó không tự nhiên mà có khi chủ thể trở thành một người dùng CodexSandbox mới. Nhiều thư mục liên quan trên Windows sẽ cấp quyền đọc/thực thi cho “Người dùng đã xác thực”. Một ví dụ đáng chú ý là thư mục hồ sơ người dùng. Theo mặc định, người dùng Windows không thể đọc các thư mục hồ sơ của người dùng Windows khác, vì vậy ngay cả các thao tác đọc tệp đơn giản cũng sẽ không thành công trong nhiều tình huống.

Để xử lý điều này, chúng tôi bổ sung một lớp nữa vào quy trình thiết lập sandbox—lớp cấp ACL đọc cho các người dùng sandbox ở những nơi mà các ACL đó có thể chưa tồn tại. Ví dụ: đến một số thư mục thường dùng trong Windows:

  • C:\Users\<real-user>
  • C:\Windows\
  • C:\Program Files\
  • C:\Program Files (x86)\
  • C:\ProgramData\

Vì danh sách thư mục này chỉ là nỗ lực tốt nhất có thể và việc cài đặt ACLs trên từng thư mục khá tốn kém, chúng tôi chạy logic này bất đồng bộ để bước thiết lập sandbox, vốn đang chặn người dùng, không phải chờ thao tác này hoàn tất.

Chúng tôi đã gói gọn logic thiết lập vào một tệp nhị phân riêng biệt, một phần là để chỉ vượt qua ranh giới UAC khi cần thiết. Nhưng lý do sâu xa hơn nằm ở kiến trúc: việc thiết lập môi trường sandbox có nhiệm vụ hoàn toàn khác so với codex.exe. Việc giữ logic thiết lập hộp cát trong một tệp nhị phân riêng biệt cho phép codex.exe hoạt động bình thường, không cần quyền quản trị; tránh việc bộ máy thiết lập chỉ dành cho Windows làm phình to codex.exe trên các nền tảng khác; tách biệt công việc thiết lập kéo dài khỏi vòng đời của tiến trình chính; và cung cấp cho chúng ta một nơi duy nhất để xử lý các đường dẫn thiết lập khác nhau mà hộp cát cần.

Sơ đồ hiển thị bước thiết lập sandbox nâng quyền chính thức đầu tiên.

Trình chạy lệnh là một tệp nhị phân mới thực sự chạy lệnh của người dùng

Vì cách Windows quản lý ranh giới đăng nhập người dùng và token, chúng tôi không thể tiếp tục tạo token bị hạn chế và sinh tiến trình với token đó như đã làm với sandbox không nâng quyền. Để thực sự sinh lệnh bằng tư cách một người dùng Windows khác, ý tưởng đầu tiên của chúng tôi là quy trình như sau:

  • codex.exe chạy với tư cách người dùng Windows thực tế. Sau đó, theo trình tự, Codex:
    • Gọi LogonUserW(...) cho người dùng sandbox.
    • Gọi CreateRestrictedToken(...) trên token người dùng sandbox đó.
    • Sử dụng token người dùng sandbox bị hạn chế đó, gọi CreateProcessAsUserW(...) để khởi chạy tiến trình con cuối cùng.

Trên thực tế, luồng hoạt động mong muốn đó không hoạt động được do rào cản về quyền tại CreateProcessAsUserW(...). Điều này có nghĩa là codex.exe có thể tạo ra một token bị hạn chế cho người dùng trong môi trường sandbox, nhưng nó không thể khởi chạy một tiến trình con với token đó một cách đáng tin cậy từ phía người dùng thực. Chúng tôi cần một quy trình đã chạy sẵn với tư cách người dùng sandbox—điều này sẽ cho phép bước hạn chế và khởi tạo cuối cùng diễn ra ở phía người dùng sandbox thay vì phía người dùng thực.

Yêu cầu đó đã dẫn đến codex-command-runner.exe, một binary mới có nhiệm vụ duy nhất là tạo một token bị hạn chế và khởi chạy lệnh được yêu cầu. Thay vì yêu cầu codex.exe tự thực hiện toàn bộ quy trình (người dùng thực → người dùng sandbox → token bị hạn chế → tiến trình con), chúng tôi chia quy trình thành hai phần:

Phần 1

  • codex.exe gọi CreateProcessWithLogonW(...) để khởi chạy codex-command-runner.exe dưới người dùng sandbox, mà chưa dùng token bị hạn chế.

Phần 2

  • Bên trong runner, OpenProcessToken(GetCurrentProcess(), ...) mở token của chính runner, vốn đã thuộc về người dùng sandbox.
  • Runner gọi GetTokenInformation(...) để trích xuất SID đăng nhập của sandbox, sau đó gọi CreateRestrictedToken(...) để tạo token bị hạn chế cuối cùng.
  • Vẫn bên trong runner, nó gọi CreateProcessAsUserW(...) với token bị hạn chế đó để khởi chạy tiến trình con thực sự.
Sơ đồ hiển thị quy trình chạy lệnh để khởi tạo các lệnh bị hạn chế.

Bức tranh tổng thể

Albert Einstein từng nói: “Mọi thứ nên được làm đơn giản nhất có thể, nhưng không đơn giản hơn.” Với tinh thần đó, thiết kế của chúng tôi giải quyết thỏa đáng từng vấn đề. Kiến trúc cuối cùng có bốn lớp mà chúng tôi đã đề cập trước đó:

  • chính codex.exe
  • codex-windows-sandbox-setup.exe để xử lý mọi công việc thiết lập liên quan đến nâng quyền
  • codex-command-runner.exe để chạy các lệnh bằng token bị hạn chế
  • Tiến trình con

Khi mới bắt đầu với dự án này, tôi chưa có hình dung rõ ràng về việc nó sẽ đi đến đâu. Cách tiếp cận của tôi là bắt đầu bằng việc gắn khả năng sandbox vào ranh giới giữa Codex và hệ điều hành. Cách tiếp cận này khá tương đồng với cách sandbox của Codex được triển khai trên MacOs và Linux.

Khi tôi hiểu thêm về những công cụ cụ thể mà Windows cung cấp, và trải qua hàng chục quyết định cân bằng giữa bảo mật với tính dễ dùng, hệ thống đã phát triển thành hình thức hiện tại—nhiều tệp nhị phân, người dùng tùy chỉnh, quy tắc tường lửa, một bước thiết lập nâng quyền, các tiến trình bất đồng bộ và nhiều thứ khác.

Đây không phải là một hệ thống đặc biệt đơn giản, nhưng mỗi phần phức tạp đều được thêm vào vì cần thiết, nhằm xây dựng một sandbox vừa an toàn vừa, trong khả năng cao nhất, không cản trở người dùng.

Sơ đồ hiển thị kiến trúc sandbox Windows cuối cùng.

Cân bằng giữa an toàn và tính hữu dụng thực tế

Trong nỗ lực mang lại trải nghiệm tốt cho người dùng Codex trên Windows, mục tiêu của chúng tôi là tạo ra thứ gì đó an toàn mà không làm giảm tính hữu dụng—mục đích cốt lõi của việc dùng Codex là để các tác nhân có thể làm việc mà không cần bạn liên tục chú ý.

Một trong những bài học lớn nhất từ dự án này là Windows không đưa sẵn cho chúng tôi một cơ chế nền tảng nào ánh xạ sạch sẽ và trực tiếp vào khái niệm “tác nhân lập trình tự động an toàn”. Chúng tôi đã kết hợp nhiều công cụ và khái niệm để xây dựng một hệ thống mạch lạc. Một số ý tưởng ban đầu đi vào ngõ cụt. Thiết kế cuối cùng là một sự lai ghép từ các nguyên mẫu trước đó, mỗi cái giải được một phần bài toán.

Bài học còn lại là bảo mật cho một tác nhân lập trình là một vấn đề to tát khác hẳn so với bảo mật ứng dụng kiểu truyền thống hơn. Codex phải hoạt động cho các quy trình làm việc thực tế của nhà phát triển. Công việc kỹ thuật ở đây là cân bằng khả năng tương thích với các khối lượng công việc mang tính tác nhân và việc thực thi thật sự. Sự căng thẳng đó đã định hình các đánh đổi trong thiết kế cuối cùng.

Tò mò muốn xem sandbox của Codex hoạt động ra sao? Hãy dùng thử.