Rust 写的 prompt 注入防火墙:一次扫描 12 微秒
每个 LLM 应用都有同样两个问题:用户把敏感数据(SSN、信用卡、API key)贴进 prompt 再发给 OpenAI/Anthropic/Google;用户(或攻击者)注入 "ignore previous instructions" 让 agent 为所欲为。
标准方案都慢:Microsoft Presidio 约 200ms/次扫描;LLM Guard 约 300ms 且要 47+ Python 依赖含 PyTorch;Lakera 是付费云 API——数据出基础设施。作者要的是本地、零网络调用、亚毫秒的 PII + 注入检测,于是有了 promptfirewall。
性能数字(criterion 实测,Apple M 系 release)
| 场景 | 延迟 |
|---|---|
| PII 扫描(发现 SSN + 信用卡) | 952 ns |
| PII 扫描(900 字节 6 类 PII) | 10.3 μs |
| 完整 PII + 注入扫描 | 11.9 μs |
| Python 调用(PyO3) | 2.2 μs/次 |
| Node.js 调用(napi-rs) | 4 μs/次 |
比 Presidio 快 15,000 倍、比 LLM Guard 快 25,000 倍(cargo bench 可复现)。
怎么做到这么快
PII 检测:无 NER、无 ML 模型,正则 + 校验和消除误报:信用卡正则 → Luhn 校验;IBAN → ISO 7064 mod-97-10;SSN → 区号校验(拒绝 000/666/900+)+ 组/序列零检查;邮箱/电话/IP/AWS Key/API Key → 正则 + 结构验证。"看起来像信用卡但 Luhn 不过?忽略。"生产里 PII 的误报比漏报更糟。
注入检测三层 + 复合打分:
- Layer 1 启发式(35+ 正则,~50μs):按攻击类别组织——指令覆盖(ignore/disregard/forget previous instructions)、角色劫持(you are now/pretend to be)、system prompt 提取、假系统 token(
<|im_start|>、###System)、越狱词(DAN、developer mode)、编码请求(base64 decode this)、多轮操纵、定界符混淆。每个模式有权重(0.60–0.95),返回最大权重。 - Layer 2 TF-IDF 分类器(~200μs):50 词表、人工 IDF 权重(ignore 2.8、jailbreak 5.2、bypass 4.0),源自 deepset/prompt-injections 数据集分析。余弦相似度打注入质心——抓启发式漏掉的新表述。
- Layer 3 熵分析(~100μs):64 字符滑窗 Shannon 熵(阈值 4.5)抓 base64 载荷;非 ASCII unicode 比例(0.15)抓同形字攻击(西里尔字符替换拉丁);嵌套
"role"/"system"JSON 抓结构化注入。
复合打分:score = max(heuristic×0.9, tfidf×0.7, entropy×0.5),两个信号都超 0.3 再乘 1.15。
实践建议
- 亚毫秒检测让"每次请求都扫"可行——不必只在可疑时启用;
- 校验和验证(Luhn/ISO 7064)是 PII 误报的杀手锏,纯正则不可靠;
- 启发式 + TF-IDF + 熵三层互补:正则抓已知、分类器抓变体、熵抓编码载荷。
来源:I built a prompt injection firewall in Rust. It scans in 12 microseconds. - DEV Community