# Dựng sandbox cho agent: rào file và rào mạng phải đi cùng nhau

> Agent càng được tự chạy lệnh ở máy khách hàng thì càng cần một hàng rào mà nó không thể thuyết phục để được cho qua.

Bản gốc: https://fdetimes.net/vi/bach-khoa/sandbox-code-execution-va-quyen-file-system-cho-agent/

Tuần đầu ở khách hàng, bạn để agent chạy test trong repo của họ. Nửa tiếng sau, bạn đã bấm "cho phép" mấy chục lần cho những lệnh như `pytest`, `ls`, `pip install`. Tới một lúc nào đó, bạn không còn đọc lệnh nữa mà chỉ bấm.

Đó là lúc rủi ro nhất. Hộp thoại xin phép chỉ bảo vệ được bạn khi người bấm còn tỉnh táo. Lối ra không phải là bấm nhanh hơn hay tắt hẳn việc hỏi, mà là dựng một sandbox: trong rào thì agent tự do, ra ngoài rào thì hệ điều hành chặn lại.

Với FDE, đây là một việc triển khai thật. Đội bảo mật của khách sẽ hỏi agent của bạn chạm được vào những gì. Trả lời "nó sẽ hỏi trước" thì họ khó tin, còn "nó không thể" thì có sức thuyết phục.

## Vì sao phải rào cả file lẫn mạng?

Simon Willison mô tả một "bộ ba chết người" (lethal trifecta): ba khả năng mà khi agent có đủ cả ba, một đoạn prompt injection đã đủ để lấy trộm dữ liệu. Một trong ba khả năng đó là liên lạc ra bên ngoài. Theo ông, sandbox phải cắt được ít nhất một chân.

Đội kỹ thuật của Anthropic, khi viết về sandbox của Claude Code, kết luận rằng sandbox hiệu quả cần cô lập cả hệ thống file lẫn mạng. Thử bỏ một nửa sẽ thấy ngay vì sao.

Nếu chỉ rào mạng, agent bị lừa vẫn sửa được file cấu hình shell để cài sẵn một lệnh chạy ngoài sandbox ở lần sau. Nếu chỉ rào file, nó vẫn đọc được mã nguồn trong workspace và gửi thẳng ra internet.

Còn một chỗ hay bị gộp nhầm. Tài liệu của Codex tách sandbox (những gì agent làm được về mặt kỹ thuật) khỏi approval policy (khi nào phải hỏi).

Đó là hai thứ phải chỉnh riêng. Đặt approval thành "cho hết" thì không thành sandbox. Còn sandbox chặt mà approval vẫn hỏi mọi thứ thì bạn lại quay về cảnh bấm liên tục.

## Rào nên đặt ở tầng nào?

Rào phải nằm ở tầng hệ điều hành, không nằm ở lớp tool hay trong prompt. Sandbox của Claude Code dựa trên bubblewrap trên Linux và Seatbelt trên macOS. Vì vậy mọi tiến trình con mà agent gọi, từ `pytest` tới một script cài đặt, đều bị rào theo.

Anthropic cũng mở mã nguồn sandbox-runtime (srt), một công cụ áp giới hạn file và mạng lên tiến trình bất kỳ mà không cần container. Công cụ này tiện khi bạn làm trên laptop, hoặc trên máy dev của khách vốn không cho chạy Docker.

Phần mạng có một chi tiết đáng học. Trên Linux, srt bỏ hẳn network namespace của tiến trình bị rào, nên mọi lưu lượng buộc phải đi qua proxy chạy trên host.

Claude Code cũng chỉ cho ra internet qua một unix domain socket nối tới proxy nằm ngoài sandbox. Agent không sửa được proxy, và vì đó là con đường duy nhất ra ngoài nên allowlist domain đặt ở proxy mới thật sự có tác dụng.

## Ví dụ: chính sách cho repo của một công ty logistics

Thử hình dung khách hàng là một công ty logistics, nhờ bạn cho agent sửa bug trong service tính phí giao hàng. Agent cần đọc code, chạy `pytest` và cài package từ mirror nội bộ. Trên máy còn có `~/.ssh`, `~/.aws` và một file `.env` chứa khóa database staging.

Hãy viết chính sách xuất phát từ những việc agent cần làm, đừng xuất phát từ những gì nó có thể muốn. Bản phác thảo dưới đây chỉ để minh họa ý, không phải cú pháp cấu hình của công cụ nào:

```text
ghi:  ./  /tmp        # ngoài ra cấm hết
./.git chỉ đọc
đọc:  mặc định cho phép
trừ ~/.ssh  ~/.aws  ./.env
mạng: mặc định cấm
chỉ cho pypi.mirror.khach-hang.example
```

Quy tắc đọc và ghi được đặt ngược nhau có chủ ý, giống cách srt làm. Đọc thì mặc định cho phép rồi chặn từng chỗ. Ghi thì mặc định cấm ở mọi nơi, chỗ nào được ghi như `.` hay `/tmp` phải mở rõ ràng.

Lý do: agent cần đọc rộng để hiểu hệ thống, còn mỗi chỗ ghi được là thêm một chỗ có thể bị cài thứ gì đó chạy về sau.

Dòng `.git` lấy từ cách Codex làm: thư mục `.git` nằm trong vùng ghi được vẫn bị khóa chỉ đọc. Nhờ vậy agent sửa được code nhưng không viết lại được lịch sử commit.

Vế mạng làm theo kiểu allowlist của srt: không khai báo domain nào nghĩa là không có mạng. Codex cũng giữ mạng tắt ở chế độ `workspace-write`, trừ khi bạn tự bật trong cấu hình.

## Chính sách chưa kiểm thì coi như chưa có

Trước khi giao agent cho khách, hãy tự đóng vai prompt injection và chạy những lệnh sau bên trong sandbox:

```bash
cat ~/.ssh/id_rsa         # phải bị chặn đọc
echo x >> ~/.bashrc       # phải bị chặn ghi
curl https://example.com  # proxy phải từ chối
git commit -am "thu"      # .git chỉ đọc, phải lỗi
```

Sau đó chạy thêm một ca kiểm chiều ngược lại: `pip install` từ mirror nội bộ phải thành công. Hàng rào chặn luôn cả việc chính đáng thì mọi người sẽ tắt nó đi. Lệnh tấn công nào lọt qua là chính sách còn lỗ, và bạn sửa ngay ở vế tương ứng.

**Điểm mấu chốt:** Bớt hỏi agent chỉ an toàn khi hàng rào bên dưới đã chặn được điều tệ nhất.

## Các bước dựng rào

Bắt đầu bằng việc liệt kê những gì agent cần làm trong một ngày ở chỗ khách: các lệnh, các thư mục, các domain.

Từ danh sách đó, viết vế ghi theo allowlist, vế đọc theo denylist những chỗ chứa bí mật, và vế mạng theo allowlist domain. Sau đó chọn cơ chế ép buộc ở tầng hệ điều hành: srt trên laptop, hoặc bubblewrap và Seatbelt nếu bạn tự dựng.

Rào xong rồi mới chỉnh approval policy. Lệnh nằm gọn trong rào thì cho tự chạy, lệnh cần vượt rào thì mới hỏi người. Cuối cùng, chạy bộ lệnh tấn công ở trên và lưu kết quả lại để đưa cho đội bảo mật của khách.

Hãy đo kết quả bằng số lần bạn phải bấm cho phép. Anthropic cho biết trong quá trình dùng nội bộ, sandbox giúp giảm 84% số lần hỏi quyền mà vẫn an toàn. Con số của bạn sẽ khác, nhưng nếu nó không giảm thì approval policy vẫn chưa tận dụng được hàng rào.

## Những lỗi hay gặp

Lỗi phổ biến nhất là mở toang mạng vì "pip cần internet". Agent chỉ cần một mirror, nên chỉ mở đúng domain đó.

Codex cloud cũng mặc định chạy pha agent ở chế độ offline, trừ khi bạn bật internet cho môi trường đó. Hãy giữ mặc định này và chỉ mở khi có lý do cụ thể.

Lỗi thứ hai là thay hàng rào bằng một bộ lọc guardrail. Willison hoài nghi những sản phẩm khoe bắt được phần lớn các vụ tấn công, vì theo ông 95% là một điểm trượt rõ ràng. Kẻ tấn công chỉ cần lọt một lần, còn hàng rào ở tầng hệ điều hành thì không phụ thuộc vào việc đoán đúng ý đồ.

Lỗi thứ ba là chỉ rào ở lớp tool, ví dụ chặn tool `read_file` đọc `~/.ssh` nhưng lại để agent gọi `cat` qua shell. Mọi tiến trình con đều phải nằm trong cùng một hàng rào.

## Đưa kỹ năng này vào CV

Khi đọc JD của các vị trí FDE làm về agent, hãy để ý những từ như "sandboxing", "least privilege", "agent security".

Trong CV, một dòng cụ thể như "thiết kế sandbox cho coding agent ở môi trường khách: chỉ ghi trong workspace, mạng đi qua proxy allowlist, kèm bộ test tấn công" có sức nặng hơn nhiều so với "có kinh nghiệm bảo mật". Khi phỏng vấn, hãy kể bạn đã cắt chân nào của bộ ba chết người và mang theo kết quả của bộ lệnh tấn công.

Khách hàng không cần agent của bạn ngoan. Họ cần nó không làm hỏng được gì, kể cả khi bị lừa.

**Thử ngay tuần này:**

- Chọn một repo của bạn, liệt kê mọi thư mục agent cần ghi và mọi domain nó cần gọi, rồi viết chính sách ba vế ra một file văn bản.
- Chạy agent trong sandbox-runtime hoặc sandbox có sẵn của công cụ bạn dùng, thử bốn lệnh tấn công trong bài và ghi lại lệnh nào lọt.
- Đếm số lần bạn phải bấm cho phép trong một giờ làm việc, trước và sau khi bật sandbox.

## Nguồn

- [Making Claude Code more secure and autonomous with sandboxing (Anthropic Engineering)](https://anthropic.com/engineering/claude-code-sandboxing)

- [anthropic-experimental/sandbox-runtime (GitHub)](https://github.com/anthropic-experimental/sandbox-runtime)

- [Agent approvals & security (OpenAI Codex docs)](https://learn.chatgpt.com/docs/agent-approvals-security)

- [The lethal trifecta for AI agents (Simon Willison's Weblog)](https://simonwillison.net/2025/Jun/16/the-lethal-trifecta/)
