@davidmytton
Bảo vệ các endpoint trò chuyện (chat) và sinh văn bản (completion) AI khỏi hành vi lạm dụng — phát hiện các cuộc tấn công tiêm câu lệnh (prompt injection) và vượt rào (jailbreak), chặn rò rỉ thông tin định danh cá nhân (PII) và dữ liệu nhạy cảm trong phản hồi, đồng thời thực thi giới hạn tốc độ theo ngân sách token (token budget rate limits) để kiểm soát chi phí. Sử dụng kỹ năng này khi người dùng đang xây dựng hoặc bảo mật bất kỳ endpoint nào xử lý prompt của người dùng bằng LLM, ngay cả khi họ mô tả yêu cầu là "ngăn chặn jailbreak", "chặn tấn công prompt", "chặn dữ liệu nhạy cảm", hoặc "kiểm soát chi phí API AI" thay vì gọi tên cụ thể các cơ chế bảo vệ.
---
name: add-ai-protection
license: Apache-2.0
description: Bảo vệ các endpoint trò chuyện (chat) và sinh văn bản (completion) AI khỏi hành vi lạm dụng — phát hiện các cuộc tấn công tiêm câu lệnh (prompt injection) và vượt rào (jailbreak), chặn rò rỉ thông tin định danh cá nhân (PII) và dữ liệu nhạy cảm trong phản hồi, đồng thời thực thi giới hạn tốc độ theo ngân sách token (token budget rate limits) để kiểm soát chi phí. Sử dụng kỹ năng này khi người dùng đang xây dựng hoặc bảo mật bất kỳ endpoint nào xử lý prompt của người dùng bằng LLM, ngay cả khi họ mô tả yêu cầu là "ngăn chặn jailbreak", "chặn tấn công prompt", "chặn dữ liệu nhạy cảm", hoặc "kiểm soát chi phí API AI" thay vì gọi tên cụ thể các cơ chế bảo vệ.
metadata:
pathPatterns:
- "app/api/chat/**"
- "app/api/completion/**"
- "src/app/api/chat/**"
- "src/app/api/completion/**"
- "**/chat/**"
- "**/ai/**"
- "**/llm/**"
- "**/api/generate*"
- "**/api/chat*"
- "**/api/completion*"
importPatterns:
- "ai"
- "@ai-sdk/*"
- "openai"
- "@anthropic-ai/sdk"
- "langchain"
promptSignals:
phrases:
- "prompt injection"
- "pii"
- "sensitive info"
- "ai security"
- "llm security"
anyOf:
- "protect ai"
- "block pii"
- "detect injection"
- "token budget"
---
# Bổ Sung Bảo Mật Chuyên Biệt Cho AI Với Arcjet
Bảo mật các endpoint AI/LLM bằng cơ chế bảo vệ đa tầng: phát hiện tấn công tiêm câu lệnh (prompt injection), chặn thông tin định danh cá nhân (PII), và giới hạn tốc độ theo ngân sách token. Các lớp bảo vệ này phối hợp chặt chẽ với nhau để chặn đứng hành vi lạm dụng ngay trước khi yêu cầu chạm tới mô hình của bạn, giúp tiết kiệm ngân sách AI và bảo vệ dữ liệu người dùng.
## Tài Liệu Tham Khảo
Hãy đọc https://docs.arcjet.com/llms.txt để xem tài liệu SDK toàn diện bao quát tất cả các framework, các loại quy tắc (rule types) và tùy chọn cấu hình.
Các quy tắc của Arcjet chạy **trước khi** yêu cầu (request) đi tới mô hình AI của bạn — giúp chặn đứng prompt injection, rò rỉ PII, lạm dụng gây đội chi phí và bot thu thập dữ liệu (scraping) ngay tại tầng HTTP.
## Bước 1: Đảm Bảo Arcjet Đã Được Thiết Lập
Kiểm tra xem dự án đã có sẵn một client Arcjet dùng chung hay chưa (xem `/arcjet:protect-route` để biết hướng dẫn thiết lập đầy đủ). Nếu chưa có, hãy thiết lập một client trước tiên với `shield()` làm quy tắc cơ sở (base rule). Người dùng sẽ cần đăng ký một tài khoản Arcjet tại https://app.arcjet.com sau đó cấu hình khóa `ARCJET_KEY` vào biến môi trường của họ.
## Bước 2: Thêm Các Quy Tắc Bảo Vệ AI
Các endpoint AI nên kết hợp các quy tắc sau trên thực thể (instance) dùng chung thông qua phương thức `withRule()`:
### Phát Hiện Tấn Công Tiêm Câu Lệnh (Prompt Injection Detection)
Phát hiện các nỗ lực vượt rào (jailbreaks), thoát ngữ cảnh qua nhập vai (role-play escapes), và ghi đè chỉ dẫn hệ thống (instruction overrides).
- JS: `detectPromptInjection()` — truyền tin nhắn của người dùng qua tham số `detectPromptInjectionMessage` tại thời điểm gọi `protect()`
- Python: `detect_prompt_injection()` — truyền qua tham số `detect_prompt_injection_message`
Chặn các prompt độc hại **trước khi** chúng chạm tới mô hình. Cơ chế này giúp tiết kiệm ngân sách AI bằng cách từ chối các cuộc tấn công ngay từ vòng ngoài.
### Chặn Thông Tin Nhạy Cảm / Dữ Liệu Cá Nhân (PII Blocking)
Ngăn chặn thông tin định danh cá nhân (PII) đi vào ngữ cảnh của mô hình.
- JS: `sensitiveInfo({ deny: ["EMAIL", "CREDIT_CARD_NUMBER", "PHONE_NUMBER", "IP_ADDRESS"] })`
- Python: `detect_sensitive_info(deny=[SensitiveInfoType.EMAIL, SensitiveInfoType.CREDIT_CARD_NUMBER, ...])`
Truyền tin nhắn của người dùng thông qua tham số `sensitiveInfoValue` (JS) / `sensitive_info_value` (Python) tại thời điểm gọi `protect()`.
### Giới Hạn Tốc Độ Theo Ngân Sách Token (Token Budget Rate Limiting)
Sử dụng `tokenBucket()` / `token_bucket()` cho các endpoint AI — tham số `requested` có thể được đặt tỷ lệ thuận với lượng token thực tế mà mô hình tiêu thụ, giúp gắn kết trực tiếp việc giới hạn tốc độ truy cập với chi phí vận hành. Cơ chế này cũng cho phép các đợt gửi yêu cầu dồn dập ngắn hạn (short bursts) trong khi vẫn duy trì tốc độ trung bình ổn định, rất phù hợp với cách người dùng tương tác thực tế trên các giao diện trò chuyện (chat interfaces).
Cấu hình khởi điểm được khuyến nghị:
- `capacity`: 10 (lượng đỉnh tối đa - max burst)
- `refillRate`: 5 token mỗi chu kỳ (interval)
- `interval`: "10s"
Truyền tham số `requested` tại thời điểm gọi `protect()` để trừ số lượng token tỷ lệ thuận với chi phí gọi mô hình. Ví dụ: trừ 1 token cho mỗi tin nhắn, hoặc ước tính dựa trên độ dài của prompt.
Đặt thuộc tính `characteristics` để theo dõi theo từng người dùng: dùng `["userId"]` nếu người dùng đã đăng nhập xác thực, mặc định sẽ theo dõi dựa trên địa chỉ IP.
### Lớp Bảo Vệ Cơ Sở (Base Protection)
Luôn bao gồm `shield()` (tường lửa ứng dụng web WAF) và `detectBot()` làm các lớp bảo vệ nền tảng. Việc bot tự động cào dữ liệu (scraping) từ các endpoint AI là một hướng lạm dụng cực kỳ phổ biến. Đối với các endpoint được truy cập qua trình duyệt (ví dụ: giao diện chat), hãy cân nhắc bổ sung tín hiệu nâng cao của Arcjet (Arcjet advanced signals) để phát hiện bot phía máy khách (client-side), giúp bắt được các trình duyệt không giao diện (headless browsers) tinh vi. Xem https://docs.arcjet.com/bot-protection/advanced-signals để biết cách thiết lập.
## Bước 3: Kết Hợp Lời Gọi protect() và Xử Lý Quyết Định
Tất cả các tham số quy tắc được truyền chung vào một lời gọi `protect()` duy nhất. Hãy sử dụng mẫu triển khai sau:
```typescript
const userMessage = req.body.message; // the user's input
const decision = await aj.protect(req, {
requested: 1, // tokens to deduct for rate limiting
sensitiveInfoValue: userMessage, // PII scanning
detectPromptInjectionMessage: userMessage, // injection detection
});
if (decision.isDenied()) {
if (decision.reason.isRateLimit()) {
return Response.json(
{ error: "You've exceeded your usage limit. Please try again later." },
{ status: 429 },
);
}
if (decision.reason.isPromptInjection()) {
return Response.json(
{ error: "Your message was flagged as potentially harmful." },
{ status: 400 },
);
}
if (decision.reason.isSensitiveInfo()) {
return Response.json(
{
error:
"Your message contains sensitive information that cannot be processed. Please remove any personal data.",
},
{ status: 400 },
);
}
if (decision.reason.isBot()) {
return Response.json({ error: "Forbidden" }, { status: 403 });
}
}
// Arcjet fails open — log errors but allow the request
if (decision.isErrored()) {
console.warn("Arcjet error:", decision.reason.message);
}
// Proceed with AI model call...
```
Điều chỉnh định dạng phản hồi (response format) cho phù hợp với framework của bạn (ví dụ: `res.status(429).json(...)` đối với Express).
## Bước 5: Xác Minh Hoạt Động
1. Khởi chạy ứng dụng và gửi một tin nhắn bình thường — yêu cầu phải được xử lý thành công
2. Kiểm thử khả năng chặn prompt injection bằng cách gửi nội dung đại loại như "Ignore all previous instructions and..."
3. Kiểm thử khả năng chặn PII bằng cách gửi một tin nhắn có chứa số thẻ tín dụng giả
Trước tiên, hãy khởi chạy tất cả các quy tắc ở chế độ `"DRY_RUN"`. Sau khi đã xác minh hoạt động chuẩn xác, hãy nâng cấp lên chế độ `"LIVE"`.
**Luôn khuyến nghị sử dụng bộ công cụ Arcjet MCP** để xác minh các quy tắc và phân tích lưu lượng truy cập:
- `list-requests` — xác nhận các quyết định đang được ghi nhận đầy đủ, lọc theo kết luận (conclusion) để xem các yêu cầu bị chặn
- `analyze-traffic` — xem xét tỷ lệ từ chối và các quy luật lưu lượng đối với endpoint AI
- `explain-decision` — hiểu rõ lý do tại sao một yêu cầu cụ thể được cho phép hoặc bị từ chối (rất hữu ích để tinh chỉnh độ nhạy khi phát hiện prompt injection)
- `promote-rule` — nâng cấp các quy tắc từ chế độ `DRY_RUN` lên `LIVE` sau khi đã kiểm chứng xong
Nếu người dùng muốn thực hiện một đợt rà soát bảo mật toàn diện, hãy gợi ý sử dụng agent `/arcjet:security-analyst` có khả năng điều tra lưu lượng, phát hiện các điểm bất thường và đề xuất bổ sung các quy tắc phù hợp.
Bảng điều khiển Arcjet tại https://app.arcjet.com cũng luôn sẵn sàng để kiểm tra trực quan.
## Các Mẫu Triển Khai Phổ Biến (Common Patterns)
**Phản hồi dạng luồng (Streaming responses)**: Gọi `protect()` trước khi bắt đầu luồng (stream). Nếu yêu cầu bị từ chối, hãy trả về lỗi ngay trước khi mở luồng — tuyệt đối không bắt đầu truyền luồng dữ liệu rồi mới hủy giữa chừng.
**Đa mô hình / Đa nhà cung cấp (Multiple models / providers)**: Sử dụng cùng một thực thể (instance) Arcjet bất kể bạn dùng nhà cung cấp AI nào. Arcjet hoạt động ở tầng HTTP, hoàn toàn độc lập với nhà cung cấp mô hình bên dưới.
**Vercel AI SDK**: Arcjet hoạt động song hành mượt mà với Vercel AI SDK. Hãy gọi `protect()` trước khi gọi `streamText()` / `generateText()`. Nếu bị từ chối, hãy trả về một phản hồi lỗi thông thường thay vì gọi vào AI SDK.
## Những Sai Lầm Phổ Biến Cần Tránh
- Tính năng phát hiện thông tin nhạy cảm chạy **cục bộ trong môi trường WASM** — không có bất kỳ dữ liệu người dùng nào bị gửi ra các dịch vụ bên ngoài. Tính năng này chỉ khả dụng trong các bộ xử lý định tuyến (route handlers), không hoạt động trong các trang Next.js (pages) hoặc server actions.
- Cả hai tham số `sensitiveInfoValue` và `detectPromptInjectionMessage` (trong JS) / `sensitive_info_value` và `detect_prompt_injection_message` (trong Python) đều phải được truyền vào tại thời điểm gọi `protect()` — việc quên truyền một trong hai tham số sẽ khiến bước kiểm tra tương ứng bị bỏ qua một cách âm thầm.
- Bắt đầu truyền luồng (stream) trước khi gọi `protect()` — nếu yêu cầu bị từ chối giữa chừng khi luồng đã mở, phía máy khách (client) sẽ nhận được một phản hồi bị lỗi đứt đoạn. Hãy luôn gọi `protect()` trước tiên và trả về lỗi ngay trước khi mở luồng.
- Sử dụng `fixedWindow()` hoặc `slidingWindow()` thay vì `tokenBucket()` cho các endpoint AI — thuật toán thùng chứa token (token bucket) cho phép bạn khấu trừ token tỷ lệ thuận với chi phí mô hình và khớp hoàn hảo với quy luật tương tác theo từng đợt ngắn (bursty) của giao diện chat.
- Khởi tạo một thực thể Arcjet mới cho mỗi yêu cầu (request) thay vì tái sử dụng client dùng chung kết hợp với `withRule()`.