Mục lục bài viết
Hãy tưởng tượng bạn mở một repository vừa clone từ GitHub và giao cho Coding Agent một nhiệm vụ rất bình thường:
“Đọc project này, chạy test, tìm nguyên nhân test fail và sửa giúp tôi.”
Để làm được việc đó, Agent cần đọc source code, chạy git, gọi package manager, thực thi test suite, tạo file, có thể khởi động compiler hoặc script Python. Nếu thiếu dependency, nó có thể muốn truy cập internet. Nếu project dùng private registry, Agent thậm chí còn cần một dạng credential nào đó.
Đây chính là lý do AI Coding Agent hữu ích.
Nhưng cũng chính là lý do nó nguy hiểm.
Trong repository có thể tồn tại một README, comment, issue, dependency metadata hoặc file cấu hình chứa một Indirect Prompt Injection. Model đọc nội dung đó như một phần context, hiểu nó như instruction, rồi quyết định thực hiện một hành động mà developer chưa bao giờ yêu cầu.
Nếu Agent chỉ có khả năng sinh text, hậu quả thường dừng ở câu trả lời sai.
Nếu Agent có shell, filesystem, network và credentials, cùng một lỗi reasoning có thể trở thành một hành động thật trên hệ điều hành.
Research ban đầu đã chỉ ra đúng sự thay đổi kiến trúc này: AI Agent không còn chỉ là một LLM thụ động mà trở thành cầu nối giữa một thành phần suy luận mang tính xác suất với filesystem, CLI, network và môi trường thực thi thực tế.
Đó là lúc sandboxing trở thành một primitive an ninh nền tảng.
Điểm quan trọng nhất cần hiểu là:
Sandbox không cố làm cho model trở nên đáng tin. Sandbox giả định model có thể sai, bị thao túng hoặc sinh hành động nguy hiểm — rồi giới hạn hậu quả mà hành động đó có thể gây ra.
Đây là một sự thay đổi rất lớn trong cách chúng ta thiết kế AI systems.
Sandboxing thực chất giải quyết vấn đề gì?
Một LLM không trực tiếp xóa file hay mở socket mạng.
Model thường chỉ sinh ra một quyết định như:
Tool:
run_command
Arguments:
["pytest", "-q"]
Agent runtime nhận quyết định đó rồi thực thi nó.
Một vòng lặp đơn giản có thể hình dung như sau:
┌───────────────┐
│ User │
└───────┬───────┘
│
▼
┌───────────────┐
│ LLM │
│ reasoning │
└───────┬───────┘
│ tool call
▼
┌───────────────┐
│ Agent Runtime │
└───────┬───────┘
│
├──────────► read_file()
│
├──────────► write_file()
│
├──────────► run_command()
│
└──────────► network_request()
Chừng nào Agent Runtime chỉ cung cấp những tool giống như:
get_weather()
search_documentation()
calculate()
blast radius còn tương đối nhỏ.
Nhưng Coding Agent thường cần một primitive mạnh hơn rất nhiều:
run_command(command)
Một shell gần như là một universal tool. Từ shell, chương trình có thể khởi động tiến trình khác, đọc filesystem, mở socket, chạy compiler, sử dụng Git, gọi package manager hoặc thực thi script.
Đó là lý do threat model thay đổi hoàn toàn.
Prompt là policy mềm, sandbox là policy cưỡng chế
Giả sử system prompt chứa:
Never access files outside /workspace.
Never access the internet.
Never read SSH credentials.
Instruction này có ích. Nó giúp model hiểu hành vi mong muốn.
Nhưng nó không phải một security boundary.
Nếu model vẫn sinh:
read_file("~/.ssh/id_ed25519")
thì điều gì ngăn thao tác này xảy ra?
Nếu câu trả lời là:
“Model đã được dặn không làm như vậy.”
hệ thống vẫn chưa có enforcement thực sự.
Một sandbox tốt khiến câu trả lời trở thành:
LLM:
"Tôi muốn đọc ~/.ssh/id_ed25519"
OS sandbox:
Permission denied.
Ở đây model không cần phải hợp tác với security policy.
Policy được thực thi bởi một thành phần khác có quyền lực cao hơn model.
Anthropic mô tả containment theo cùng nguyên tắc: model-layer defenses như system prompt, classifier và training có thể làm thay đổi xác suất hành vi, nhưng không tạo ra giới hạn tuyệt đối; environment-level defenses như process sandbox, VM, filesystem boundary và egress control mới đặt ra giới hạn kỹ thuật về những gì Agent thực sự chạm tới được.
Đây chính là mental model quan trọng nhất của sandboxing.
Một sandbox đúng nghĩa phải cô lập những gì?
Nói “chạy Agent trong container” vẫn chưa trả lời được câu hỏi security.
Ta cần hỏi cụ thể hơn:
Agent đang được phép đọc gì, ghi gì, gọi gì, kết nối đâu và sử dụng danh tính nào?
Một execution sandbox dành cho AI Agent thường cần ít nhất năm lớp kiểm soát.
┌─────────────────┐
│ AI Agent │
└────────┬────────┘
│
┌──────────────▼──────────────┐
│ Execution Sandbox │
│ │
│ Filesystem boundary │
│ Process/syscall boundary │
│ Network boundary │
│ Resource boundary │
│ Credential boundary │
└──────────────┬──────────────┘
│
controlled
access
│
┌──────────────▼──────────────┐
│ External systems / services │
└─────────────────────────────┘
Mỗi boundary giải quyết một loại failure khác nhau.
1. Filesystem boundary
Coding Agent cần filesystem để hoạt động, nhưng hiếm khi nó cần toàn bộ filesystem của developer.
Thông thường Agent chỉ cần:
/workspace/project
/tmp
và có thể cần đọc một số system library.
Điều đó không có nghĩa Agent cần quyền truy cập:
~/.ssh/
~/.aws/
~/.kube/
~/.gnupg/
~/Documents/
Docker socket
browser profiles
Một filesystem sandbox tốt có thể thiết lập:
/workspace read-write
/usr read-only
/tmp temporary
~/.ssh unavailable
~/.aws unavailable
/var/run/docker.sock unavailable
OpenAI mô tả Codex theo cùng hướng: sandbox quyết định Agent có thể ghi ở đâu, path nào được bảo vệ và network có khả dụng hay không; chế độ mặc định có thể cho phép ghi trong workspace trong khi vẫn giữ các vùng khác bên ngoài boundary.
Điều đáng chú ý là read permission cũng là capability.
Một Agent không cần ghi vào SSH key để gây rủi ro. Chỉ cần đọc được credential và có đường egress, credential đó đã có khả năng bị exfiltrate.
2. Network boundary
Filesystem isolation ngăn Agent chạm tới dữ liệu nhất định.
Network isolation kiểm soát dữ liệu mà Agent có thể đưa ra ngoài hoặc tải vào trong.
Một policy yếu thường là:
Internet access: enabled
Trong khi một policy production tốt hơn thường giống:
Default:
DENY
Allowed:
pypi.org
github.com
internal-package-registry.example
Blocked:
everything else
Điều này đặc biệt quan trọng với Indirect Prompt Injection.
Giả sử một file độc hại khiến Agent muốn gửi source code ra một endpoint bên ngoài.
Prompt classifier có thể phát hiện.
Model có thể tự từ chối.
Tool gateway có thể chặn.
Nhưng ngay cả khi tất cả chúng thất bại, egress policy vẫn có thể khiến kết nối mạng không tồn tại.
OpenAI hiện cũng vận hành Codex với managed network policies thay vì cấp outbound access không giới hạn; các destination dự kiến có thể được allow, destination khác bị block hoặc yêu cầu approval.
Network sandboxing vì vậy không đơn thuần là:
“Không cho Agent dùng internet.”
Nó là:
Biến network access thành một capability cụ thể thay vì ambient authority mặc định.
3. Process và syscall boundary
Ngay cả khi Agent chỉ chạy một chương trình hợp lệ, chương trình đó có thể tạo thêm process.
Ví dụ:
Agent
│
└─ Python
│
└─ compiler
│
└─ helper process
Security policy phải propagate xuống toàn bộ process tree.
Nếu chỉ kiểm tra command đầu tiên nhưng process con chạy ngoài sandbox, boundary gần như mất ý nghĩa.
Ở tầng thấp hơn còn có system calls — syscalls.
Ứng dụng Linux không trực tiếp điều khiển disk hay network hardware. Nó yêu cầu kernel thực hiện thông qua các syscall như:
open()
read()
write()
execve()
socket()
connect()
mount()
Một số sandbox sử dụng kernel primitives để hạn chế syscall.
Một số đi xa hơn và đặt một lớp kernel khác giữa workload với host kernel.
Đây là nơi những công nghệ như gVisor xuất hiện.
4. Resource boundary
Một Agent không cần có ý định xấu để gây sự cố.
Nó có thể vô tình chạy:
while True:
...
hoặc tạo quá nhiều process, dùng hết disk, RAM hoặc CPU.
Do đó sandbox thường cần:
CPU quota
memory limit
process limit
disk quota
execution timeout
Đây là điểm khác biệt giữa security và reliability, nhưng trong Agent runtime hai vấn đề liên quan chặt chẽ.
Một hành động ngoài dự đoán không nên có khả năng làm cạn tài nguyên cả host.
5. Credential boundary
Đây là lớp thường bị bỏ quên nhất.
Giả sử Agent được chạy trong một microVM cực kỳ mạnh về isolation.
Nhưng bên trong microVM có:
AWS_ADMIN_ACCESS_KEY
Sandbox vẫn có thể bảo vệ host.
Nhưng nó không thể ngăn Agent sử dụng credential hợp lệ để gọi AWS API mà credential đó được phép truy cập.
Nói cách khác:
Sandbox giới hạn môi trường thực thi, nhưng credential quyết định quyền lực mà môi trường đó có đối với thế giới bên ngoài.
Anthropic áp dụng một pattern đáng chú ý cho Claude Code trên web: credentials nhạy cảm như Git credentials hoặc signing keys không được đặt trực tiếp trong sandbox. Thay vào đó, một proxy bên ngoài sandbox thực hiện authentication và có thể kiểm tra operation trước khi gắn credential thật.
Mental model trở thành:
Agent
│
│ temporary scoped identity
▼
Sandbox
│
▼
Credential / Policy Proxy
│
│ real credential
▼
GitHub / Cloud / Internal API
Đây mạnh hơn rất nhiều so với:
Agent
│
│ admin credential
▼
Internet
Vì sao command allowlist vẫn có thể thất bại?
Một approach khá tự nhiên là:
Allow:
git
grep
find
go test
Block:
bash
curl
ssh
Nhìn qua, điều này có vẻ hợp lý.
Nhưng command name không mô tả đầy đủ hành vi của command.
Nhiều Unix tools là những chương trình cực kỳ mạnh. Một số có thể gọi process khác, ghi file, tải plugin, đọc config hoặc diễn giải argument theo cách biến một command tưởng như vô hại thành primitive mạnh hơn nhiều.
Đây là vấn đề semantic gap:
Policy engine nhìn thấy:
"command X"
Operating system thực thi:
"toàn bộ semantics của command X + arguments + shell parsing"
Khoảng cách giữa hai cách hiểu này từng tạo ra các vulnerability thực tế trong AI coding tools.
CVE-2025-54795: parser và execution không đồng ý về command
NVD ghi nhận CVE-2025-54795 trong Claude Code: các phiên bản trước 1.0.20 có lỗi command parsing khiến confirmation prompt có thể bị bypass để kích hoạt một untrusted command. Việc khai thác đáng tin cậy yêu cầu attacker đưa được untrusted content vào context của Claude Code.
Điều đáng học ở đây không phải payload cụ thể.
Điều đáng học là kiến trúc:
Security parser
│
│ thinks command is safe
▼
Command execution
│
│ interprets input differently
▼
Unexpected behavior
Nếu parser dùng một grammar nhưng shell dùng một grammar khác, attacker sẽ tìm kiếm phần chênh lệch giữa hai grammar.
CVE-2025-54131: allowlist không hiểu đầy đủ shell syntax
Cursor cũng từng có một vấn đề tương tự. Theo NVD, các phiên bản dưới 1.3 có thể bị bypass allowlist trong auto-run mode thông qua shell substitution syntax; attack có thể được kết hợp với indirect prompt injection. Vấn đề được sửa trong version 1.3.
Hai case này dẫn tới một nguyên tắc quan trọng:
Đừng xây security boundary bằng cách regex một shell command rồi hy vọng parser của bạn hiểu shell giống shell.
Tool API nên hẹp hơn shell
Nếu Agent cần đọc một file, API tốt hơn thường là:
read_file(path="/workspace/app.py")
thay vì:
run_shell("cat /workspace/app.py")
Nếu cần tìm text:
search_files(
root="/workspace",
pattern="TODO"
)
thường dễ kiểm soát hơn:
run_shell("...")
Mỗi abstraction hẹp hơn sẽ giảm số semantics mà security layer phải hiểu.
Khi thực sự cần gọi subprocess, một pattern an toàn hơn là truyền arguments dưới dạng cấu trúc thay vì nối chúng thành shell string:
import subprocess
subprocess.run(
["git", "status", "--short"],
shell=False,
check=True,
timeout=30,
)
Điểm đáng chú ý không nằm ở syntax Python.
Nó nằm ở việc application giữ được ranh giới:
program = git
arg1 = status
arg2 = --short
thay vì biến mọi thứ thành một chuỗi rồi giao lại cho shell diễn giải lần thứ hai.
Tuy nhiên, shell=False không biến một command nguy hiểm thành command an toàn. Một binary hợp lệ vẫn có thể có những option mạnh.
Vì thế một tool gateway production thường cần validation ở cấp operation, không chỉ cấp executable.
Sandboxing có nhiều cấp độ — container, gVisor, microVM và WASM không giống nhau
Không có một công nghệ sandbox tốt nhất cho mọi Agent.
Lựa chọn phụ thuộc vào câu hỏi:
“Mã chạy bên trong này không đáng tin tới mức nào, và nó cần Linux compatibility tới đâu?”
Native OS sandbox / container primitives
Linux đã cung cấp nhiều primitive rất mạnh:
namespaces
cgroups
seccomp
Linux capabilities
Landlock
SELinux / AppArmor
Chúng có thể giới hạn process, resource, filesystem và syscall với overhead rất thấp.
Đây cũng là những primitive rất phù hợp cho local Coding Agent.
Tuy nhiên container thông thường vẫn chia sẻ host kernel.
Điều đó tạo ra một trust assumption quan trọng:
Application
│
Container
│
Shared Linux kernel
│
Host
Nếu workload là code tương đối đáng tin, đây có thể là trade-off rất tốt.
Nếu platform chạy arbitrary code từ hàng nghìn tenant không tin nhau, ta thường muốn boundary mạnh hơn.
gVisor: đặt một application kernel giữa workload và host
gVisor chọn một hướng khá thú vị.
Thay vì cho application nói chuyện trực tiếp với host Linux kernel, gVisor cung cấp một Linux-like application kernel chạy trong userspace.
Kiến trúc đơn giản hóa:
Application
│
│ syscalls
▼
┌──────────────┐
│ gVisor │
│ application │
│ kernel │
└──────┬───────┘
│
▼
Host Linux Kernel
Theo tài liệu chính thức, gVisor triển khai Linux-like interface bằng một application kernel viết bằng Go và sử dụng OCI runtime runsc, nhờ đó có thể tích hợp với Docker và Kubernetes.
Ý tưởng security ở đây là giảm lượng host-kernel surface mà code không đáng tin có thể tiếp xúc trực tiếp.
Đổi lại, syscall virtualization không miễn phí.
Những workload có tần suất syscall hoặc filesystem I/O cao có thể chịu overhead lớn hơn workload thuần compute, và gVisor cũng không triển khai mọi Linux syscall với mức compatibility giống native Linux.
Do đó gVisor thường hấp dẫn khi bạn muốn:
container-like developer experience
+
stronger isolation than a normal shared-kernel container
mà chưa muốn trả toàn bộ complexity của VM.
Firecracker: mỗi sandbox có guest kernel riêng
Firecracker đi xa hơn.
Thay vì chia sẻ Linux kernel của host, workload chạy trong một microVM sử dụng KVM.
Application
│
Guest Linux Kernel
│
Firecracker VMM
│
KVM
│
Host Kernel
Khi attacker muốn đi từ code bên trong workload tới host, boundary phải đi qua nhiều lớp hơn.
Firecracker được AWS thiết kế với device model tối giản để giảm attack surface. Trong công bố ban đầu, AWS báo cáo microVM có thể khởi động nhanh tới khoảng 125 ms và sử dụng khoảng 5 MiB memory overhead trong cấu hình của họ; những số này nên được xem là đặc tính thiết kế/benchmark của Firecracker chứ không phải SLA cho mọi platform xây trên nó.
Điểm mạnh lớn của microVM đối với Coding Agent là compatibility.
Bên trong vẫn là Linux environment thực sự:
Python
Node.js
gcc
git
package manager
subprocess
native libraries
Agent có cảm giác đang sở hữu một máy riêng.
Đó chính xác là abstraction phù hợp với nhiều code-execution workloads.
Nhược điểm là infrastructure phức tạp hơn: boot image, networking, storage, snapshot, scheduling, lifecycle và observability đều cần được quản lý.
WebAssembly: capability-first nhưng compatibility hẹp hơn
WebAssembly tiếp cận bài toán theo hướng khác.
Thay vì cho chương trình một OS rồi hạn chế nó, WebAssembly runtime bắt đầu từ một môi trường rất ít authority.
WASI đặc biệt được thiết kế theo capability model: một module không mặc định sở hữu ambient authority mà chỉ có thể sử dụng những capability host cấp cho nó.
Mental model gần giống:
WASM module
Cannot:
access filesystem
access network
use host resources
Unless:
host explicitly grants capability
Đây là security model rất hấp dẫn.
Nhưng general-purpose Coding Agent lại thường muốn:
apt install
npm install
git
gcc
native binaries
fork/exec
arbitrary Linux tooling
Đây không phải sweet spot tự nhiên của WASM.
WASM phù hợp hơn với những workload có interface rõ ràng, ví dụ:
transform this JSON
evaluate this expression
run this plugin
execute this user function
process this document
Trong khi microVM thường phù hợp hơn với:
"Đây là một Linux workspace. Hãy tự giải quyết project này."
So sánh các isolation model
| Mô hình | Isolation boundary | Linux compatibility | Startup / overhead | Phù hợp nhất |
|---|---|---|---|---|
| OS sandbox / container | Host kernel + policy | Rất cao | Thấp | Local agents, trusted hoặc semi-trusted workloads |
| gVisor | Userspace application kernel | Cao nhưng không tuyệt đối | Trung bình | Multi-tenant containers cần isolation mạnh hơn |
| Firecracker / microVM | Guest kernel + hardware virtualization | Rất cao | Cao hơn container nhưng vẫn tối ưu cho ephemeral workloads | Arbitrary code execution, coding agents, hostile workloads |
| WASM / WASI | Language/runtime capability sandbox | Hạn chế hơn | Rất thấp | Plugins, functions, deterministic compute |
Đây không phải bảng xếp hạng “tốt → xấu”.
Mỗi model đang tối ưu một constraint khác nhau.
Nếu bạn cần chạy:
untrusted JavaScript function
microVM có thể là overkill.
Nếu bạn cần cho Agent:
clone repository
install dependencies
compile native code
run integration tests
WASM có thể trở thành một restriction quá lớn.
Security architecture tốt không chọn công nghệ mạnh nhất.
Nó chọn boundary nhỏ nhất vẫn đủ mạnh cho threat model.
🏗️ Production Note — Sandbox không nên đứng một mình
Một mistake nguy hiểm là xây một microVM thật mạnh rồi nghĩ:
“Xong, Agent an toàn.”
Không hẳn.
Sandbox chủ yếu trả lời:
“Process này có thể chạm tới những resource nào?”
Nó không tự động trả lời:
“Operation này có phù hợp với business policy hay không?”
Ví dụ một Agent được phép gọi API:
DELETE /staging/test-data
Sandbox không thể biết request đó là thao tác test hợp lệ hay model vừa hiểu sai yêu cầu.
Ta cần nhiều lớp.
Một kiến trúc production hợp lý hơn là:
Untrusted Content
README / Web / MCP / Issue
│
▼
┌─────────────┐
│ LLM │
└──────┬──────┘
│
proposal
│
▼
┌──────────────────┐
│ Tool Schema + │
│ Input Validation │
└────────┬─────────┘
│
▼
┌──────────────────┐
│ Policy / Approval│
│ Gateway │
└────────┬─────────┘
│
▼
┌───────────────────────────┐
│ Sandbox │
│ │
│ filesystem restrictions │
│ process isolation │
│ resource limits │
│ default-deny network │
└─────────────┬─────────────┘
│
▼
┌──────────────────┐
│ Scoped Credential│
│ Proxy │
└────────┬─────────┘
│
▼
External System
Điều thú vị ở architecture này là không có lớp nào phải hoàn hảo.
Nếu prompt defense fail, tool validation vẫn còn.
Nếu tool validation fail, policy gateway vẫn còn.
Nếu policy fail, sandbox vẫn hạn chế filesystem và network.
Nếu Agent cần external API, scoped credential giảm blast radius.
Đó chính là defense in depth.
Approval và sandbox giải quyết hai vấn đề khác nhau
Hai khái niệm này thường bị trộn lẫn.
Sandbox hỏi:
Agent có khả năng làm gì?
Ví dụ:
Can write only /workspace
Cannot access network
Cannot read ~/.ssh
Approval hỏi:
Agent có được phép tại thời điểm này thực hiện operation cụ thể hay không?
Ví dụ:
Agent wants network access to new-domain.example
→ Ask user
Một hệ thống chỉ dùng approval sẽ gây approval fatigue.
Nếu Agent hỏi:
Approve ls?
Approve grep?
Approve pytest?
Approve git status?
Approve cat app.py?
developer dần có xu hướng click Allow mà không đọc.
Ngược lại, cho Agent full autonomy không có sandbox lại mở blast radius quá lớn.
Mô hình tốt hơn là:
Low risk + inside sandbox
│
└── automatic
Crosses security boundary
│
└── approval / policy review
OpenAI cũng mô tả sandboxing và approvals là hai cơ chế bổ trợ: sandbox xác định technical boundary, trong khi approval policy quyết định khi nào hành động vượt boundary cần được review.
Credentials nên sống ngắn hơn Agent
Một anti-pattern phổ biến:
export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...
start-agent
Từ góc nhìn Agent, credential này trở thành ambient authority.
Bất kỳ process nào bên trong environment có thể đọc nó nếu permissions cho phép.
Một pattern tốt hơn là:
Agent requests operation
│
▼
Policy service
│
├─ verify identity
├─ verify scope
├─ verify resource
└─ verify expiry
│
▼
short-lived credential
│
▼
specific operation
Credential lý tưởng nên:
- có scope hẹp;
- chỉ dùng cho resource cần thiết;
- expire nhanh;
- không tồn tại lâu hơn sandbox session;
- tránh quyền admin;
- có audit trail;
- có thể revoke độc lập.
Điều này đặc biệt quan trọng trong multi-agent architecture.
Nếu Agent A và Agent B có nhiệm vụ khác nhau, việc cả hai nhận cùng service-account credential sẽ phá hỏng phần lớn isolation mà sandbox vừa tạo ra.
Từ một sandbox tới hàng nghìn Agent: bài toán lifecycle
Nếu chỉ chạy một Coding Agent trên laptop, process sandbox có thể đủ.
Nhưng platform phục vụ hàng nghìn Agent xuất hiện thêm một vấn đề:
Sandbox không chỉ là security boundary. Nó còn trở thành một lifecycle primitive.
Một AI workspace có hành vi khác web server thông thường.
Web server thường:
start
↓
serve continuously
↓
replace when needed
Agent workspace có thể:
start
↓
work 40 seconds
↓
idle 20 minutes
↓
resume
↓
install dependencies
↓
idle
↓
resume
Nó còn có thể cần:
persistent filesystem
stable identity
ephemeral compute
fast resume
Kubernetes SIG Apps đang phát triển Agent Sandbox chính vì mismatch này. Tài liệu Kubernetes tháng 3/2026 mô tả Agent workload như isolated, stateful singleton workspace và giới thiệu Sandbox CRD, đồng thời hỗ trợ runtime như gVisor hoặc Kata Containers.
Architecture trở thành:
Agent Framework
│
│ request workspace
▼
SandboxClaim
│
▼
SandboxTemplate
│
▼
Pre-warmed Sandbox
│
├── gVisor
└── Kata / VM-based runtime
Project còn có SandboxWarmPool, giữ một tập sandbox đã provision sẵn để giảm cold-start khi Agent cần workspace. Kubernetes cũng nhấn mạnh rằng một pod mới có thể thêm khoảng một giây overhead trong flow tương tác, vì vậy pre-warming trở thành trade-off giữa latency và idle compute.
Đây là một insight quan trọng:
Khi Agent infrastructure phát triển đủ lớn, sandbox không còn chỉ là “security wrapper quanh process”. Nó trở thành một resource type của platform.
🔬 Deep Dive — Vì sao “default deny” mạnh hơn việc phát hiện hành vi xấu?
Có hai triết lý security khác nhau.
Detect bad behavior
Allow everything
│
▼
Try to recognize attacks
│
▼
Block suspicious actions
Vấn đề là attacker và model có không gian hành động gần như vô hạn.
Bạn phải dự đoán:
malicious command
malicious URL
malicious argument
malicious tool sequence
malicious encoding
malicious dependency
...
Trong khi đó, capability-based design đảo bài toán.
Define allowed capabilities
Deny everything
│
▼
Grant only:
workspace write
package registry access
test database
│
▼
Everything else impossible
Thay vì hỏi:
“Lệnh này có phải attack không?”
system hỏi:
“Agent có capability thực hiện việc này không?”
Đây thường là một câu hỏi dễ trả lời hơn nhiều.
Giả sử một Coding Agent chỉ cần:
read repository
write repository
run tests
download packages from registry
thì kiến trúc có thể cấp chính xác bốn capability đó.
Agent có thể sinh hàng triệu command khác nhau.
Nhưng blast radius vẫn bị đóng trong cùng một capability envelope.
Đó chính là lý do sandboxing scale tốt hơn prompt-based prohibition: security team không cần dự đoán mọi suy luận tương lai của model.
Sáu sai lầm phổ biến khi sandbox AI Agents
1. “System prompt đã cấm rồi nên đủ an toàn”
System prompt là defense layer hữu ích.
Nhưng nó không phải enforcement boundary.
Nếu một operation không bao giờ được phép xảy ra, nên làm nó không thể thực hiện ở tầng infrastructure, thay vì chỉ yêu cầu model đừng làm.
2. “Docker container nghĩa là code đã hoàn toàn isolated”
Container cung cấp isolation rất hữu ích, nhưng container thông thường vẫn chia sẻ host kernel.
Với trusted internal workloads, đây thường là trade-off hợp lý.
Với hostile multi-tenant arbitrary code execution, cần đánh giá thêm gVisor, VM-based isolation hoặc các boundary mạnh hơn thay vì coi mọi container là tương đương microVM.
3. “Allowlist command name là đủ”
Không đủ nếu arguments thay đổi semantics.
Security layer cần hiểu operation, argument schema và execution path thực tế.
Các CVE của Coding Agent năm 2025 cho thấy mismatch giữa command parser, allowlist và shell semantics có thể biến một command được đánh giá là hợp lệ thành arbitrary command execution.
4. “Sandbox rồi thì có thể để internet mở”
Filesystem isolation và network isolation giải quyết hai threat khác nhau.
Nếu Agent đọc được dữ liệu nhạy cảm và có unrestricted egress, prompt injection vẫn có thể tạo đường exfiltration.
Network nên được coi là capability, không phải default.
5. “Credential nằm trong sandbox thì vẫn an toàn vì VM rất chắc”
MicroVM có thể bảo vệ host khỏi workload.
Nó không làm một AWS credential quyền cao trở nên ít quyền hơn.
Credential scope phải được thiết kế độc lập với compute isolation.
6. “Sandbox càng chặt càng tốt”
Một sandbox khiến Agent không thể cài dependency, chạy compiler hoặc thực hiện test cần thiết sẽ khiến developer liên tục disable sandbox.
Đó là failure về security design.
Boundary tốt phải đạt được:
enough freedom to finish the task
+
not enough freedom to cause unacceptable damage
Đây không phải bài toán tìm maximum restriction.
Đây là bài toán tìm minimum required capability.
Một blueprint thực tế cho Coding Agent trong production
Nếu xây một Coding Agent service từ đầu, một baseline architecture có thể bắt đầu như sau:
User
│
▼
Agent Orchestrator
│
▼
┌──────────────┐
Untrusted content ─►│ LLM │
└──────┬───────┘
│
tool proposal
│
▼
┌───────────────────┐
│ Tool Policy Layer │
│ │
│ schema validation │
│ operation policy │
│ approval rules │
└─────────┬─────────┘
│
▼
┌─────────────────────────┐
│ Ephemeral Sandbox │
│ │
│ /workspace RW │
│ system files RO │
│ secrets absent │
│ CPU/RAM/PID capped │
│ network deny │
└───────────┬─────────────┘
│
│ approved egress
▼
┌───────────────────┐
│ Network / Auth │
│ Proxy │
└─────────┬─────────┘
│
scoped access
│
▼
Git / Registry / API
Sau đó mới chọn implementation.
Nếu chạy local developer tool:
OS-native sandbox
+
workspace filesystem policy
+
network deny-by-default
có thể là lựa chọn tốt.
Nếu chạy multi-tenant SaaS nơi Agent thực thi arbitrary repository:
gVisor
hoặc
microVM-based isolation
có thể hợp lý hơn.
Nếu workload chỉ là user-defined function với interface cố định:
WASM/WASI
có thể cung cấp một capability model gọn hơn nhiều.
Nếu platform cần hàng nghìn persistent Agent workspaces trên Kubernetes, orchestration layer như Agent Sandbox bắt đầu trở nên đáng quan tâm.
Sandboxing thay đổi cách chúng ta nghĩ về AI Safety
Trong chatbot truyền thống, một phần lớn security discussion xoay quanh:
Model có trả lời điều gì không?
Agentic systems buộc chúng ta đặt thêm một câu hỏi quan trọng hơn:
Model có thể làm được điều gì?
Hai câu hỏi này hoàn toàn khác nhau.
Một prompt injection khiến chatbot nói sai là một lỗi ở information layer.
Một prompt injection khiến Coding Agent thực thi operation ngoài dự kiến là một lỗi ở capability layer.
Và capability layer không nên được bảo vệ chỉ bằng natural-language instruction.
Nó cần những primitive quen thuộc của security engineering:
least privilege
process isolation
filesystem permissions
network segmentation
short-lived credentials
resource quotas
audit logs
human approval
defense in depth
AI làm cách chúng ta sử dụng những primitive này thay đổi.
Nhưng nó không khiến các nguyên lý đó biến mất.
Ngược lại, khi model ngày càng có khả năng lập kế hoạch, sử dụng tool và tự sửa lỗi, việc đặt một boundary độc lập với reasoning của model càng trở nên quan trọng.
Một Coding Agent tốt nên được tự do thử nhiều cách khác nhau để giải quyết bài toán.
Nhưng sự tự do đó cần tồn tại bên trong một chiếc hộp có giới hạn rõ ràng.
Đó chính là ý nghĩa thực sự của sandboxing.
Không phải:
“Làm sao đảm bảo Agent không bao giờ có một ý tưởng nguy hiểm?”
Mà là:
“Nếu Agent có một ý tưởng nguy hiểm, chúng ta đã thiết kế hệ thống để ý tưởng đó không có đủ capability trở thành một sự cố lớn hay chưa?”
Khi câu trả lời là có, ta đã chuyển security từ việc tin vào hành vi của model sang việc kiểm soát quyền lực của model.
Và đó mới là nền móng phù hợp để đưa AI Agents vào production.
Nguồn tham khảo
- OpenAI — Running Codex safely at OpenAI.
- OpenAI — Building a safe, effective sandbox to enable Codex on Windows.
- Anthropic — Making Claude Code more secure and autonomous with sandboxing.
- Anthropic — How we contain Claude across products.
- NIST NVD — CVE-2025-54795: Claude Code command parsing vulnerability.
- NIST NVD — CVE-2025-54131: Cursor allowlist bypass.
- gVisor — What is gVisor?.
- AWS — Firecracker: Lightweight Virtualization for Serverless Computing.
- Kubernetes — Running Agents on Kubernetes with Agent Sandbox.
- WebAssembly / WASI — WebAssembly Security và WASI capability-based sandbox.



