Model Context Protocol trong Production: security boundary, least privilege và isolation cho AI agent tool runtime

Sơ đồ security boundary cho Model Context Protocol với agent runtime, policy layer, MCP server và downstream systems
MCP là capability plane của agent runtime, nên phải được thiết kế như security boundary thực sự.

Model Context Protocol (MCP) đang được nhắc tới như lớp chuẩn hóa để AI agent nói chuyện với tool, data source và capability bên ngoài. Ở tầng demo, MCP khá hấp dẫn: một protocol chung, nhiều server tái sử dụng được, client dễ mở rộng toolset hơn so với việc hardcode từng integration.

Nhưng ở production, thứ nguy hiểm nhất của MCP cũng chính là thứ làm nó mạnh: nó biến “tool access” thành một bề mặt thực thi có tính plug-in. Nếu boundary không rõ, MCP server rất dễ trở thành đường vòng cho permission creep, data exfiltration, prompt-to-action escalation, hoặc thậm chí remote code execution gián tiếp.

Nói ngắn gọn: MCP không phải chỉ là protocol cho context. Nó là capability plane của agent runtime. Và capability plane thì phải được thiết kế như một security boundary thật sự, không phải như một adapter tiện lợi.

Bài này đi sâu vào các vấn đề mà team backend, platform, security hoặc AI engineering cần nghĩ tới khi đưa MCP vào môi trường thật: trust boundary nằm ở đâu, vì sao “tool available = tool executable” là giả định nguy hiểm, cách thiết kế least privilege, credential scoping, sandbox, approval gate, audit trail và checklist hardening trước khi cho agent chạm hệ thống nội bộ.

MCP làm thay đổi mô hình rủi ro của AI agent như thế nào?

Trước MCP, nhiều hệ thống agent được viết theo kiểu orchestration kín:

  • tool nào dùng được là do code app quyết định;
  • input/output đi qua schema nội bộ;
  • credential được map theo từng integration;
  • bề mặt tấn công tương đối tập trung.

Khi chuyển sang MCP, bạn có thêm một abstraction layer mới:

  • client model/client runtime;
  • MCP transport;
  • MCP server;
  • capability surface do server expose;
  • đôi khi thêm local process bridge hoặc remote connector.

Điều này tạo ra 3 thay đổi lớn về risk:

1. Capability discovery trở nên động hơn

Agent không còn chỉ gọi những hàm được lập trình tĩnh. Nó có thể “nhìn thấy” nhiều tool hơn, đôi khi do một MCP server tự công bố. Nếu policy layer yếu, agent sẽ có xu hướng thử capability mới chỉ vì nó xuất hiện trong context.

2. Credential path trở nên khó nhìn hơn

Credential có thể nằm ở:

  • client runtime;
  • MCP server process;
  • sidecar/container;
  • downstream API mà MCP server đại diện;
  • local filesystem hoặc secret store.

Nếu không map rõ trust chain, bạn sẽ rất khó trả lời câu hỏi đơn giản: agent đang thao tác với quyền của ai?

3. Prompt injection có thể leo thang thành capability abuse

Một tài liệu độc hại, một web page chứa prompt injection, hay một email được ingest có thể không chỉ làm model trả lời sai. Nó có thể đẩy agent sang quyết định gọi tool có side effect qua MCP. Khi đó bài toán không còn là content safety nữa, mà là execution safety.

Đừng coi MCP server là extension tiện lợi; hãy coi nó là privileged broker

Luồng zero trust cho request đi qua Model Context Protocol trước khi tới downstream API
Zero-trust cho MCP nghĩa là mọi lớp đều có validation, scope enforcement và audit thay vì tin mù vào model hoặc client.

Một sai lầm phổ biến là xem MCP server như plugin kỹ thuật thuần túy: “nó chỉ bọc API thôi mà”. Thực tế, MCP server thường làm ba việc rất nhạy cảm:

  1. công bố capability cho agent;
  2. nhận instruction gián tiếp từ model qua client/orchestrator;
  3. đại diện thực thi hành động vào downstream system.

Ba việc này ghép lại biến MCP server thành privileged broker. Một broker như vậy phải có policy và identity rõ ràng.

Nếu không, bạn sẽ gặp các anti-pattern sau:

  • một MCP server expose cả read-only lẫn write capability nhưng không phân tầng risk;
  • mọi tool cùng dùng một service account “cho tiện”;
  • model được nhìn thấy tên tool quá mạnh dù phần lớn request không bao giờ nên dùng;
  • transport giữa client và server không có auth/attestation rõ;
  • server trả lỗi mơ hồ khiến orchestration layer retry sai loại hành động.

Security boundary thực sự nằm ở đâu?

Nhiều team trả lời “ở MCP server”. Câu này chỉ đúng một nửa.

Boundary thực tế nên được nhìn theo 4 lớp:

Lớp 1: Conversation boundary

Đây là ranh giới giữa dữ liệu model đọc được và instruction nào được phép ảnh hưởng tới execution. Prompt, retrieval chunk, web content và user message không thể mặc định có quyền đề xuất hành động nguy hiểm mà không qua policy.

Lớp 2: Orchestration boundary

Đây là nơi quyết định:

  • tool nào hiện ra với phiên này;
  • tool nào được gọi trong ngữ cảnh hiện tại;
  • request nào cần approval;
  • request nào bị chặn dù model muốn dùng.

Nếu orchestration layer không làm boundary mà chỉ pass-through sang MCP, bạn đã giao quá nhiều quyền cho model.

Lớp 3: MCP server boundary

MCP server phải tự bảo vệ mình trước client sai, model sai và upstream sai. Nó không được giả định rằng caller đã validate đầy đủ. Server cần:

  • validate schema và semantic policy;
  • enforce scope;
  • log identity + correlation;
  • chống lạm dụng rate / volume / payload;
  • phân biệt read vs write vs admin capability.

Lớp 4: Downstream resource boundary

Dù MCP server có policy, downstream system vẫn nên có guardrail riêng:

  • RBAC/ABAC ở API đích;
  • scoped token;
  • immutable audit log;
  • quota / limit;
  • idempotency với write action.

Không nên đặt toàn bộ niềm tin vào một lớp ở giữa.

Least privilege cho MCP không phải khẩu hiệu; nó là data model và deployment model

Ma trận least privilege cho MCP capability theo session actor resource operation và thời gian
Least privilege cho MCP chỉ có ý nghĩa khi được tách theo session, actor, resource, operation class và thời gian.

“Least privilege” nghe rất quen, nhưng với agent + MCP nó dễ bị nói suông hơn làm thật. Lý do là capability không chỉ nằm ở credential, mà còn ở sự hiện diện của tool, phạm vi dữ liệu tool nhìn thấy, và kiểu action tool được phép thực thi.

Một thiết kế tốt nên tách privilege theo ít nhất 5 chiều.

1. Scope theo phiên hoặc task

Không phải phiên nào cũng cần cùng một toolset. Nếu user đang hỏi phân tích log read-only, đừng expose tool gửi email, sửa ticket hay chạy lệnh production. Tool availability phải là dynamic policy, không phải catalog cố định cho mọi run.

2. Scope theo actor

Agent thay mặt user nào thì chỉ nên thấy capability tương ứng với user đó hoặc với delegated role được cấp rõ. Tránh pattern service account toàn quyền đứng sau mọi yêu cầu; nó làm mất dấu “ai thực sự ra quyết định” và khiến audit vô nghĩa.

3. Scope theo resource

Cùng là ticket.update, nhưng cập nhật ticket trong project A và project B có thể khác mức rủi ro. MCP tool nên hỗ trợ resource-level constraint thay vì chỉ action-level allow/deny.

4. Scope theo operation class

Tối thiểu nên tách:

  • read-only;
  • write idempotent;
  • write non-idempotent;
  • admin/destructive.

Một orchestrator trưởng thành thường chỉ cho model auto-execute nhóm 1, cân nhắc nhóm 2, còn nhóm 3-4 cần approval hoặc bị chặn hẳn.

5. Scope theo thời gian

Credential cấp cho run ngắn hạn an toàn hơn credential sống dai. Session-bound token, short-lived delegated credential hoặc signed request capability giúp giảm blast radius khi token bị lộ qua log, crash dump hoặc misconfiguration.

Vấn đề lớn nhất không phải model “thông minh quá”, mà là capability surface “rộng quá”

Khi sự cố xảy ra, nhiều người có xu hướng đổ lỗi cho model hallucination. Nhưng trong khá nhiều incident, model chỉ làm điều hoàn toàn hợp logic từ góc nhìn của nó: thấy tool, nghĩ tool hữu ích, gọi tool.

Gốc rễ nằm ở capability surface quá rộng:

  • tool mạnh xuất hiện trong mọi phiên;
  • description của tool mơ hồ hoặc quá hấp dẫn;
  • không có policy chặn tool theo context;
  • approval gate đặt sau khi side effect đã bắt đầu;
  • không có safe fallback khi tool bị từ chối.

Nếu một model có thể “nhìn thấy” run_shell, read_secrets, delete_record hoặc push_config trong context thông thường, bạn đã thất bại ở architecture trước khi nói tới prompt safety.

MCP server nên được thiết kế như zero-trust adapter

Một MCP server production-grade không nên tin tuyệt đối vào client. Hãy giả định:

  • client gửi input đúng schema nhưng sai ý định;
  • caller có thể bị prompt injection điều khiển;
  • request có thể bị replay;
  • correlation chain có thể thiếu hoặc sai;
  • downstream có thể timeout sau khi đã commit.

Từ giả định đó, server nên có các lớp bảo vệ sau.

Semantic validation

Schema hợp lệ chưa đủ. Ví dụ:

  • path có nằm trong allowlist không;
  • repository có thuộc organization được phép không;
  • command template có chứa biến nguy hiểm không;
  • email recipient có thuộc domain cho phép không.

Semantic validation là thứ chặn “JSON hợp lệ nhưng hành động sai”.

Policy enforcement độc lập với model

Server phải có ability tự nói “không” dù model rất tự tin. Ví dụ:

  • từ chối tool write ngoài giờ change window;
  • từ chối query vượt row limit;
  • từ chối read file ngoài workspace sandbox;
  • yêu cầu approval token hợp lệ trước khi thực thi.

Replay và idempotency guard

Đặc biệt với side effect, mỗi tool call nên có:

  • tool call id;
  • idempotency key;
  • dedupe window;
  • execution state.

Nếu transport hoặc client retry, server phải biết đó là replay hợp lệ hay request mới.

Structured error taxonomy

Đừng trả về một cục failed. Hãy chuẩn hóa lỗi thành các nhóm như:

  • POLICY_DENIED
  • VALIDATION_FAILED
  • AUTH_SCOPE_MISMATCH
  • RATE_LIMITED
  • DEPENDENCY_TIMEOUT
  • SIDE_EFFECT_AMBIGUOUS

Taxonomy này rất quan trọng để orchestration layer không retry sai hoặc diễn giải sai cho model.

Sandbox và isolation: nếu tool runtime có thể chạm host, bạn phải sợ đúng mức

Một số MCP server chỉ wrap HTTP API. Một số khác cho phép truy cập filesystem, shell, database local hoặc desktop app bridge. Từ đây trở đi, risk tăng rất nhanh.

Khi nào cần sandbox mạnh?

Gần như luôn cần sandbox mạnh nếu tool có thể:

  • đọc/ghi filesystem;
  • chạy command;
  • truy cập mạng tự do;
  • load plugin hoặc script;
  • dùng credential của host;
  • nói chuyện với production control plane.

Mức isolation tối thiểu nên cân nhắc

  1. Process isolation

- tách process thay vì nhúng trong cùng runtime với agent.

  1. Filesystem sandbox

- read/write chỉ trong mount path rõ ràng; tránh full host access.

  1. Network egress control

- allowlist domain hoặc network segment; không để tool muốn gọi đâu thì gọi.

  1. Credential isolation

- mỗi MCP server hoặc mỗi capability class có secret riêng; không share một token omnibus.

  1. OS-level restriction

- seccomp/AppArmor/container profile nếu môi trường cho phép.

  1. Resource quota

- CPU, memory, file descriptor, concurrency limit để tránh một tool lỗi kéo sập cả node.

Nói cách khác: đừng dùng MCP như shortcut để bỏ qua sandbox mà bạn vốn đã cần cho bất kỳ plugin runtime nào.

Approval gate phải nằm trước side effect, không phải sau khi “agent đã quyết xong”

State machine approval gate cho MCP side effect tool trong production
Approval thật phải chặn trước side effect và có state machine kiểm chứng được, không phải lời nhắc mềm trong prompt.

Có một kiểu approval giả rất phổ biến:

  1. agent chuẩn bị action;
  2. agent hoặc tool đã tạo side effect một phần;
  3. UI mới hiện “bạn có muốn xác nhận không?”.

Đó không phải approval thật. Đó là audit muộn.

Với MCP, approval cần được model hóa như một state transition rõ ràng:

  • proposed
  • awaiting_approval
  • approved
  • executed
  • rejected
  • expired

Tool server hoặc orchestration layer không được phép nhảy từ proposed sang executed nếu chưa có approval artifact hợp lệ. Artifact này có thể là signed token, workflow decision id, hoặc session-bound confirmation context.

Điều quan trọng là approval không được sống trong prompt text. Nó phải là dữ liệu policy có thể verify.

Audit trail: nếu không reconstruct được “agent đã làm gì”, bạn chưa sẵn sàng production

Một run AI agent có thể đi qua nhiều tool và nhiều boundary. Khi có incident, bạn cần trả lời:

  • user nào khởi tạo hành vi;
  • model nào đề xuất tool call;
  • orchestration policy nào đã allow;
  • MCP server nào thực thi;
  • credential scope nào được dùng;
  • resource nào bị tác động;
  • có approval không;
  • tool call nào retry;
  • downstream request id là gì;
  • kết cục cuối cùng là success, denied hay ambiguous.

Tối thiểu mỗi tool call nên log:

  • trace_id
  • agent_run_id
  • tool_call_id
  • mcp_server_id
  • actor_principal
  • delegated_scope
  • resource_scope
  • approval_state
  • idempotency_key
  • latency_ms
  • outcome_class
  • downstream_correlation_id

Nếu thiếu các trường này, postmortem sẽ biến thành đoán mò.

Prompt injection và untrusted content phải được coi là execution input risk

MCP làm bài toán prompt injection nghiêm trọng hơn vì tác động không dừng ở answer quality. Một đoạn text độc hại có thể cố ép agent:

  • liệt kê tool khả dụng;
  • gọi tool đọc dữ liệu nhạy cảm;
  • ghi đè instruction bằng “system-like text”;
  • chuyển từ read sang write action;
  • yêu cầu bỏ qua approval.

Cách phòng không phải chỉ là thêm câu “ignore malicious instruction”. Cần nhiều lớp:

  1. tách untrusted content khỏi policy channel;
  2. classify content source và risk level;
  3. disable high-risk tool cho run ingest content không tin cậy;
  4. yêu cầu human review khi từ untrusted content dẫn tới external side effect;
  5. log provenance: hành động này bắt nguồn từ đâu.

Nếu không theo dõi provenance, bạn sẽ không biết request nguy hiểm xuất phát từ user thật hay từ tài liệu độc hại mà agent vừa đọc.

Một deployment pattern thực tế cho MCP an toàn hơn

So sánh blast radius giữa MCP server all in one và MCP server tách biệt theo domain
Tách MCP server theo domain giúp giảm blast radius khi một capability hoặc credential bị lạm dụng.

Một kiến trúc tương đối lành mạnh thường có dạng:

  • Agent runtime: không giữ credential mạnh; chỉ giữ context và policy token ngắn hạn.
  • Policy/orchestration layer: quyết định tool visibility, approval state, capability mapping.
  • MCP gateway hoặc broker: xác thực caller, gắn correlation, enforce coarse-grained rule.
  • MCP server chuyên biệt theo domain: CRM, repo, docs, issue tracker, filesystem… mỗi loại có privilege và sandbox riêng.
  • Downstream API: vẫn giữ RBAC, audit và quota riêng.

Thiết kế này có thêm chút phức tạp vận hành, nhưng đổi lại:

  • blast radius nhỏ hơn;
  • dễ audit hơn;
  • dễ xoay vòng credential hơn;
  • dễ vô hiệu hóa một capability đang lỗi mà không kéo sập cả hệ.

Checklist hardening trước khi đưa MCP vào production

Trước khi nói tới benchmark hay UX, nên trả lời được các câu này:

Về capability surface

  • Tool nào là read-only, tool nào có side effect?
  • Tool nào thực sự cần xuất hiện với model trong từng task?
  • Có tool nào “quá mạnh để tồn tại mặc định” không?

Về identity và credential

  • Agent thực thi với quyền của user, service account hay delegated role?
  • Credential có scope ngắn hạn và giới hạn resource không?
  • Có dùng chung một token cho quá nhiều capability không?

Về policy và approval

  • Approval có là state có thể verify không?
  • Policy deny có được enforce ở server, không chỉ ở prompt, không?
  • Có chặn destructive action ngoài maintenance window không?

Về isolation

  • MCP server chạy ở đâu, quyền gì, chạm được gì?
  • Có egress control, filesystem sandbox và resource quota không?
  • Tool runtime có thể đụng secret của host hoặc CI agent không?

Về audit và incident response

  • Có trace xuyên suốt từ model decision tới downstream request không?
  • Có phân biệt denied, failed, ambiguous, replayed không?
  • Có playbook revoke capability nếu một MCP server bị compromise không?

Kết luận

MCP là bước tiến đáng giá cho hệ sinh thái AI agent vì nó chuẩn hóa cách tool và context được kết nối. Nhưng càng chuẩn hóa được capability plane, bạn càng phải xem nó như hạ tầng quan trọng chứ không phải phụ kiện tiện lợi.

Trong production, câu hỏi không phải là “MCP có mạnh không?”. Câu hỏi đúng là: bạn đã đặt security boundary đủ rõ để sức mạnh đó không biến thành đường tắt tới sự cố chưa?

Nếu coi MCP server là privileged broker, áp least privilege thật sự theo session/actor/resource/operation/time, tách approval khỏi prompt, và đầu tư sandbox + audit trail, bạn sẽ có một nền agent runtime linh hoạt mà vẫn kiểm soát được blast radius. Còn nếu chỉ ghép model với một đống tool rồi hy vọng prompt đủ ngoan, bạn đang dựng một hệ phân tán có quyền lực cao nhưng thiếu kỷ luật cơ bản của production engineering.

Đọc tiếp trong cluster AI engineering / production reliability