关于 detecting-indirect-prompt-injection
用于在 LLM Agent 读取外部数据前检测间接提示注入的安全技能,结合隐藏文本提取、内容规范化、规则与模型扫描,并支持后续处置。
主要功能
- 01提取网页、PDF 和图像中的隐藏文本
- 02规范化并解码混淆内容
- 03结合规则与分类模型扫描
- 04选择拦截、清理或放行
- 05生成结构化检测遥测
适用场景
- 01在 Agent 读取前筛查第三方内容
- 02检查文档和图像中的隐藏指令
- 03在红队演练中验证注入防护
- 04调查 Agent 行为异常
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mukul975/ anthropic-cybersecurity-skills --skill detecting-indirect-prompt-injection安装后在 Claude Code 中输入/detecting-indirect-prompt-injection确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
LICENSEreferences/api-reference.mdstandards.mdscripts/agent.py详细介绍
检测间接提示词注入
仅限授权使用通知: 本技能中的脚本会扫描不可信内容以查找注入载荷,并运行检测器模型。请仅对你有权处理的数据运行扫描,并将任何提取出的载荷视为实时不可信输入 —— 切勿将它们重新粘贴回具有特权的 LLM 上下文中。
概述
间接提示词注入(MITRE ATLAS AML.T0051.001、OWASP LLM01:2025)发生在由 LLM 驱动的 Agent 摄入外部内容时 —— 它浏览的网页、它摘要的 PDF 或电子邮件、它进行 OCR 的图像、它读取的工具结果 —— 而该内容包含隐藏指令,模型随后会像这些指令来自开发者或用户一样执行它们。由于 Agent 将其上下文窗口中的所有 token 视为同等权威,攻击者只要控制任何被消费的产物,就能劫持 Agent 的行为:窃取对话历史、重定向工具调用、泄露机密,或通过已连接的系统进行横向移动。
与直接注入(用户输入攻击内容)不同,间接注入通过看似可信的数据通道到达,这就是为什么简单的输入过滤会漏掉它。载荷以多种形式隐藏:网页中的 HTML 注释和 display:none/零宽文本,PDF 中的白底白字或微小字体文本,图像中的 alt 文本和 EXIF 元数据,渲染为像素的文本(对轻度 OCR 过滤不可见,但会被多模态模型读取),Unicode 标签字符/零宽字符,以及 Base64/ROT13 混淆。本技能构建了一条检测流水线,在产物到达模型之前对其规范化并扫描,结合启发式/正则检测、专用检测器模型(Meta Prompt Guard 2、通过 LLM Guard 使用的 ProtectAI deberta-v3 prompt-injection 分类器),以及针对图像的多模态提取,然后定义响应操作和检测遥测。
何时使用
- 在构建或加固会浏览网页、读取电子邮件、摘要文档或处理用户上传文件/图像的 Agent 时。
- 当你需要在摄入第三方数据的 LLM 前面设置内容净化关卡时。
- 在 AI 红队/蓝队演练期间,验证检索产物中注入的指令能否被捕获。
- 在调查 Agent 表现得像收到了并非你编写的指令的事件时。
- 作为对添加到知识库的文档进行 CI/CD 预摄入扫描时。
前置条件
- Python 3.10+ 和虚拟环境。
- 安装检测工具:
python -m venv .venv && source .venv/bin/activate
# LLM Guard — input/output scanners incl. PromptInjection
pip install llm-guard
# Hugging Face transformers for Prompt Guard 2 / deberta classifiers
pip install transformers torch
# Content extraction: HTML, PDF, images
pip install beautifulsoup4 pypdf pillow pytesseract
# pytesseract requires the Tesseract OCR engine:
# Debian/Ubuntu: sudo apt-get install -y tesseract-ocr
# macOS: brew install tesseract
# Windows: choco install tesseract
- 在 Hugging Face 上获得对
meta-llama/Llama-Prompt-Guard-2-86M的(受限)访问权限,或使用开放的protectai/deberta-v3-base-prompt-injection-v2分类器。
目标
- 从网页、PDF 和图像中提取人眼不可见和被混淆的文本。
- 在扫描前对内容进行规范化(去除零宽字符、解码 Base64/ROT13、展平 Unicode)。
- 运行启发式和基于 ML 的注入检测器(LLM Guard PromptInjection 扫描器、Prompt Guard 2)。
- 为每个产物评分,并在模型摄入前执行阻止 / 净化 / 允许决策。
- 输出适合 SIEM 的结构化检测遥测,并将发现映射到 ATLAS AML.T0051.001。
MITRE ATT&CK 映射
| ID | 官方名称 | 相关性 |
|---|---|---|
| AML.T0051.001 | LLM Prompt Injection: Indirect | 本技能检测和缓解的具体技术 |
| AML.T0051 | LLM Prompt Injection | 涵盖所有提示词注入变体的父技术 |
| AML.T0057 | LLM Data Leakage | 此检测所防范的间接注入的常见目标 |
| AML.T0053 | LLM Plugin Compromise | 注入的指令经常以 Agent 的工具/插件为目标 |
工作流
1. 从网页内容中提取隐藏文本
提取人类永远看不到但模型会看到的注释、隐藏元素和元数据。
# extract_html.py
from bs4 import BeautifulSoup, Comment
def extract_hidden(html: str):
soup = BeautifulSoup(html, "html.parser")
hidden = []
for c in soup.find_all(string=lambda t: isinstance(t, Comment)):
hidden.append(("comment", c.strip()))
for el in soup.select('[style*="display:none"],[style*="visibility:hidden"],[hidden]'):
hidden.append(("css-hidden", el.get_text(strip=True)))
for img in soup.find_all("img"):
if img.get("alt"):
hidden.append(("alt-text", img["alt"]))
return [h for h in hidden if h[1]]
2. 规范化并解除混淆
去除零宽字符 / Unicode 标签字符,并解码常见编码,以便检测器看到真正的载荷。
# normalize.py
import base64, codecs, re, unicodedata
ZERO_WIDTH = dict.fromkeys(map(ord, ""), None)
TAG_RANGE = range(0xE0000, 0xE0080) # Unicode tag chars used to smuggle text
def normalize(text: str) -> str:
text = text.translate(ZERO_WIDTH)
text = "".join(ch for ch in text if ord(ch) not in TAG_RANGE)
text = unicodedata.normalize("NFKC", text)
for token in re.findall(r"[A-Za-z0-9+/=]{20,}", text):
try:
decoded = base64.b64decode(token).decode("utf-8", "ignore")
if decoded.isprintable():
text += f"\n[decoded-b64] {decoded}"
except Exception:
pass
text += "\n[decoded-rot13] " + codecs.decode(text, "rot_13")
return text
3. 使用 LLM Guard 的 PromptInjection 扫描器进行扫描
LLM Guard 封装了一个 transformer 分类器,并针对每个输入返回一个风险评分。
# scan_llmguard.py
from llm_guard.input_scanners import PromptInjection
from llm_guard.input_scanners.prompt_injection import MatchType
scanner = PromptInjection(threshold=0.5, match_type=MatchType.FULL)
def scan(text: str):
sanitized, is_valid, risk = scanner.scan(text)
return {"is_valid": is_valid, "risk": risk} # is_valid=False => injection detected
4. 添加专用检测模型(Prompt Guard 2 / deberta)
运行 Meta Prompt Guard 2(或开源的 ProtectAI deberta 分类器)以获取第二意见。
# detector_model.py
from transformers import pipeline
# Open classifier (no gating); swap to meta-llama/Llama-Prompt-Guard-2-86M if licensed
clf = pipeline("text-classification",
model="protectai/deberta-v3-base-prompt-injection-v2")
def is_injection(text: str, threshold: float = 0.5) -> bool:
out = clf(text[:512])[0]
return out["label"].upper() == "INJECTION" and out["score"] >= threshold
5. 提取并扫描图像中渲染的文本
多模态 Agent 会读取绘制在像素中的文本;对其执行 OCR,并运行相同的扫描器。
# scan_image.py
from PIL import Image
import pytesseract
def ocr(path: str) -> str:
return pytesseract.image_to_string(Image.open(path))
# Feed ocr(path) through normalize() + scan() + is_injection()
6. 强制执行决策并发出遥测数据
将各信号合并为 block / sanitize / allow,并为 SIEM 记录结构化事件。
# decide.py
import json, hashlib
from datetime import datetime, timezone
def decide(source, raw, normalized, llmguard_invalid, model_flag):
flagged = llmguard_invalid or model_flag
event = {
"ts": datetime.now(timezone.utc).isoformat(),
"source": source,
"sha256": hashlib.sha256(raw.encode("utf-8", "ignore")).hexdigest(),
"atlas": "AML.T0051.001",
"llmguard_injection": llmguard_invalid,
"model_injection": model_flag,
"decision": "block" if flagged else "allow",
}
print(json.dumps(event))
return event["decision"]
7. 在语料库上验证并调整阈值
在由干净和注入样本组成的带标签数据集上运行流水线,测量精确率/召回率,并调整 threshold 以在误报与漏检注入之间取得平衡。每当 Agent 的模型或数据摄取来源发生变化时,都要重新测试。
工具与资源
| 工具 | 用途 | 来源 |
|---|---|---|
| LLM Guard | 输入/输出扫描器,包括 PromptInjection | https://github.com/protectai/llm-guard |
| Meta Prompt Guard 2 | 专用越狱/注入分类器 | https://huggingface.co/meta-llama/Llama-Prompt-Guard-2-86M |
| ProtectAI deberta-v3 | 开源提示词注入分类器 | https://huggingface.co/protectai/deberta-v3-base-prompt-injection-v2 |
| BeautifulSoup4 | HTML 解析 / 隐藏元素提取 | https://www.crummy.com/software/BeautifulSoup/ |
| pytesseract / Tesseract | 从图像中 OCR 文本 | https://github.com/madmaze/pytesseract |
| MITRE ATLAS | AI 威胁技术分类体系 | https://atlas.mitre.org/ |
| OWASP LLM01:2025 | 提示词注入参考 | https://genai.owasp.org/llmrisk/llm01-prompt-injection/ |
检测面参考
| 检测面 | 隐藏技术 | 提取步骤 |
|---|---|---|
| 网页 | HTML 注释、display:none、alt 文本 | BeautifulSoup 隐藏元素处理 |
| 白色/微小字体、页面外文本 | pypdf 文本提取 + 归一化 | |
| 图像 | 渲染像素、EXIF、alt 文本 | OCR + 元数据读取 |
| 任意文本 | 零宽 / Unicode 标签字符 | normalize() 去混淆 |
| 任意文本 | Base64 / ROT13 编码 | normalize() 中的解码处理 |
验证标准
- 已为 HTML、PDF 和图像实现隐藏文本提取
- 归一化会剥离零宽/Unicode 标签字符并解码 Base64/ROT13
- 已集成 LLM Guard PromptInjection 扫描器并返回风险评分
- 已集成专用检测模型(Prompt Guard 2 或 deberta)作为第二信号
- OCR 路径可扫描图像中渲染的文本
- 在模型摄取之前强制执行 block/sanitize/allow 决策
- 为 SIEM 发出带 ATLAS 映射的结构化检测遥测数据
- 已在带标签的语料库上验证流水线并测量精确率/召回率
- 阈值已调整并记录成文档
- 发现结果已映射到 MITRE ATLAS AML.T0051.001 和 OWASP LLM01:2025