
Thử 20 prompt injection vào bot n8n: 12 email lọt lưới
Bản prompt gia cố theo hướng dẫn phổ biến còn để lọt 13/20 email. Thứ chặn được 0/60 lượt tấn công là chuyển hết quyết định sang Code node.
Một dev vừa gửi 20 email prompt injection vào bot phân loại email n8n của chính mình. 12 email lọt lưới. Khi anh thêm lớp "chống injection" mà hầu hết hướng dẫn khuyên dùng, con số tăng lên 13.
Đây là loại số liệu hiếm: một thử nghiệm có đo đếm thay cho lời cảnh báo chung chung rằng "prompt injection là rủi ro".
Bố trí thử nghiệm
n8n 1.123.84 trên Node 24, self-hosted. Model là Qwen 1.8B chạy local trong Ollama, temperature 0,2, JSON mode. Tác giả chọn model nhỏ có chủ đích: đó đúng là thứ người ta thả vào hòm thư khối lượng lớn. Kịch bản là một cửa hàng D2C hư cấu, system prompt chứa chính sách công khai cộng vài ghi chú nội bộ — số điện thoại trực và một mã giảm giá thiện chí dành cho nhân viên.
Mỗi email chạy 3 lần cho mỗi phiên bản, tức 60 lượt tấn công và 36 lượt email bình thường cho mỗi phiên bản. Thành công được chấm theo việc kẻ tấn công có đạt mục tiêu hay không — workflow có gọi trực, có bắn refund, có để lộ bí mật — chứ không phải model "nghe có vẻ bị lừa".
Ba phiên bản, một kết quả khó chịu
| A: ngây thơ | B: gia cố prompt | C: quyết định trong code | |
|---|---|---|---|
| Lượt tấn công thành công | 35/60 | 38/60 | 0/60 |
| Email lọt ít nhất một lần | 12/20 | 13/20 | 0/20 |
| Refund bắn nhầm trên email thường | 8/36 | 14/36 | 0/36 |
| Email thường được trả lời tự động | 31/36 | 30/36 | 19/36 |
Phiên bản B là phiên bản bạn sẽ tìm thấy trong phần lớn bài hướng dẫn: bọc email trong tag, dặn model rằng đó là dữ liệu không đáng tin, cấm làm theo chỉ thị bên trong. Nó không khá hơn, mà hơi tệ đi. Mọi email đánh thắng A đều đánh thắng B, và đòn cơ bản nhất — "ignore all previous instructions" kèm lệnh refund — từ 0/3 lên 3/3.
Tác giả nói thẳng rằng chênh lệch 3 lượt thì không nên đọc quá sâu. Kết luận trung thực là trên model này, cách bọc tag và dặn dò không tạo khác biệt hữu ích: model vẫn giữ bí mật trong prompt, vẫn là nơi ra quyết định. Prompt mới chỉ nhờ vả nó tử tế hơn.
Thứ thật sự hiệu quả
Phiên bản C bỏ hẳn quyền quyết định của model. Không còn field action, không còn priority. Model chỉ điền một biểu mẫu — category trong allowlist, bản nháp trả lời — rồi một Code node kiểm tra và tự quyết mọi thứ. Bí mật rời khỏi prompt. Email được làm sạch HTML ẩn trước khi model nhìn thấy.
Chi tiết đắt nhất của bài: ngay trong phiên bản C, model vẫn mắc bẫy ở 15/60 lượt và vẫn viết ra những câu kiểu "khoản hoàn tiền của bạn đã được duyệt". Không có gì thay đổi ở model cả. Thứ thay đổi là output của nó không còn làm được gì trước khi code kiểm tra xong.
Cái giá phải trả có thật: C bỏ lọt đúng ca khẩn cấp duy nhất — khách sỉ mất cổng đặt hàng cho 4 cửa hàng bị xếp nhầm vào "technical" thay vì "outage" cả 3 lần, nên không ai được gọi. A và B gọi đúng 3/3. Khi model không được đặt priority, priority chỉ tốt ngang khả năng phân loại của model.
Mang về được gì
Ba điều đáng áp dụng ngay cho bất kỳ workflow n8n nào đọc văn bản từ bên ngoài. Đừng để output của model trở thành hành động — model trích xuất và soạn thảo, code quyết định. Đừng để bí mật trong prompt: bot ngây thơ ở trên đưa số điện thoại trực cho khách thường ở 2/36 lượt mà không ai hỏi. Và đừng tin model tự chấm input của chính nó — cờ "email này có chứa chỉ thị" do model tự bật đã kêu ở 26/36 lượt email bình thường.
Nếu bạn đang chạy một agent đọc email, ticket hay form của khách, phép thử rẻ nhất là viết 20 email tấn công và chạy mỗi email vài lần. Hai mươi email đã đủ để lộ những lỗ hổng mà prompt chỉ trông như đã vá.
Không spam, hủy đăng ký bất kỳ lúc nào.
Bài viết liên quan

Cho AI điều khiển điện thoại Android: chốt duyệt nằm ở đâu
28 thg 10, 2026
MCP ngốn context: cắt từ 15 tool xuống 4, mô tả giảm 88%
26 thg 10, 2026