Bài 4 — Least Privilege: giới hạn quyền và phạm vi tool của agent
Guardrail input/output lọc nội dung; nhưng phòng thủ mạnh nhất là không trao quyền mà agent không cần. Nguyên tắc least privilege (đặc quyền tối thiểu): agent chỉ được thấy đúng tool và đúng dữ liệu cần cho nhiệm vụ hiện tại — không hơn.
Vì sao quyền là gốc rễ an toàn
Một agent bị prompt-injection nhưng chỉ có tool read_faq() thì thiệt hại tối đa là... đọc FAQ. Cũng agent đó nếu có execute_sql() hoặc transfer_money() thì injection thành thảm họa. Giới hạn quyền biến một lỗ hổng nghiêm trọng thành một phiền toái nhỏ.
Bốn trục để siết quyền
- Tool scope: agent chỉ được cấp tập tool tối thiểu. Đừng đưa cả 40 tool cho một agent chỉ cần 3.
- Data scope: query gắn
WHERE user_id = :current_user. Agent hỗ trợ khách A không được đọc dữ liệu khách B. - Credential scope: dùng API key/role riêng cho agent, quyền hẹp (read-only nếu chỉ cần đọc), có thể thu hồi độc lập.
- Time/context scope: quyền nâng cao chỉ mở tạm thời cho một tác vụ, rồi đóng lại.
Ví dụ: khai báo tool theo vai trò
TOOL_POLICY = {
"support_readonly": ["get_order", "search_faq"], # Tier 0
"support_agent": ["get_order", "search_faq", "create_ticket"], # +Tier 1
"billing_agent": ["get_order", "issue_refund"], # +Tier 2 (cần HITL)
# KHÔNG role nào của agent tự động có execute_sql / delete_user
}
def tools_for(role: str, all_tools: dict) -> dict:
allowed = TOOL_POLICY.get(role, [])
return {name: all_tools[name] for name in allowed if name in all_tools}
# Data scope: mọi truy vấn bị ràng buộc theo người dùng hiện tại
def get_order(order_id, ctx):
return db.query(
"SELECT * FROM orders WHERE id=%s AND user_id=%s", # ràng buộc cứng
[order_id, ctx.user_id]
)
Quan trọng: việc lọc tool xảy ra ở backend, không phụ thuộc model "tự giác không gọi". Model không được đưa vào lựa chọn thì không thể gọi.
Ví dụ: credential hẹp cho database
# SAI: agent dùng user DB toàn quyền
DATABASE_URL=postgres://admin:...@db/prod # có DROP, DELETE...
# ĐÚNG: role riêng, chỉ SELECT trên view an toàn
CREATE ROLE agent_ro LOGIN;
GRANT SELECT ON orders_safe_view TO agent_ro; # không cột nhạy cảm
-- không GRANT INSERT/UPDATE/DELETE
Các bước áp dụng least privilege
- Kiểm kê tool + dữ liệu mỗi agent đang có quyền chạm tới.
- Hỏi "có thực sự cần không?" cho từng quyền. Nghi ngờ thì bỏ.
- Tạo role/policy ánh xạ agent → tập tool tối thiểu.
- Ràng buộc data scope ở tầng truy vấn (filter theo tenant/user), không tin tham số model đưa.
- Cấp credential hẹp riêng cho agent (read-only khi có thể), tách khỏi credential ứng dụng chính.
- Just-in-time elevation: nếu cần quyền cao, mở tạm cho đúng tác vụ rồi thu hồi.
- Audit định kỳ quyền dư thừa và thu lại.
Checklist least privilege
- [ ] Agent có tool nào nó chưa từng dùng trong 30 ngày không? → cân nhắc gỡ
- [ ] Mọi query có ràng buộc theo user/tenant ở backend không?
- [ ] Credential của agent có phải read-only khi tác vụ chỉ đọc không?
- [ ] Có tool phá hủy nào nằm trong tập mặc định của agent không?
- [ ] Quyền nâng cao có tự động hết hạn không?
Sai lầm thường gặp
- "Cho hết cho tiện". Trao cả kho tool để khỏi phải nghĩ — biến mọi injection thành rủi ro tối đa.
- Data scope dựa vào prompt. Dặn model "chỉ xem dữ liệu của user hiện tại" nhưng không filter ở DB → IDOR: model bị lừa đọc dữ liệu người khác.
- Một credential quyền cao dùng chung. Không thu hồi được riêng, không giới hạn được phạm vi, lộ là mất tất cả.
- Quên thu hồi elevation. Mở quyền admin cho một tác vụ rồi để mở vĩnh viễn.
- Tin tham số tool từ model. Model có thể bị dụ truyền
user_idcủa người khác; luôn lấy identity từ context phiên đã xác thực, không từ đối số model tự sinh.
Học xong bài này rồi?
Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu,
và học hết khóa thì có chứng chỉ.
Lưu tiến độ của tôi