pjcampbe11/ipi-detect

GitHub: pjcampbe11/ipi-detect

面向 Agentic LLM 系统的间接提示注入防御检测工具,通过内容预扫描与运行时行为监控的双层架构,基于真实 CVE 事件检测并阻断注入攻击。

Stars: 1 | Forks: 0

# ipi-detect [![Python](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/) [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](#license) [![Dependencies](https://img.shields.io/badge/runtime%20deps-none%20(stdlib)-success.svg)](#install) [![Coverage verifier](https://img.shields.io/badge/coverage-34%20rules%20verified%20%2F%2013%20gaps%20documented-orange.svg)](#threat-model--detection-coverage-detections) [![Eval](https://img.shields.io/badge/corpus%20eval-precision%201.000%20%2F%20recall%200.933-blueviolet.svg)](#run-the-eval) 针对 Agentic LLM 系统中**间接提示注入**的检测。 这是 SpecterOps “构建间接提示注入工作流”研究的逆向检测端对应物:它不是用于生成和优化 payload 的测试框架,而是用于测量是否存在注入内容以及 Agent 是否正在执行这些内容。 ![ipi-detect 演示 — 对 EchoLeak 模式 payload 的内容扫描,归因于 CVE-2025-32711 的运行时阻断,IOC 命中,测试套件,覆盖率验证器,以及语料库评估记分板](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/1721d47807202336.gif) ## 目录 - [为什么需要它](#why-this-exists) - [基于已记录、可归因的安全事件](#grounded-in-documented-attributable-incidents) - [双层架构](#the-two-layers) - [威胁模型与检测覆盖率 (`detections/`)](#threat-model--detection-coverage-detections) - [为什么要双层架构](#why-two-layers) - [基于真实环境遥测数据](#grounded-in-in-the-wild-telemetry-not-just-lab-payloads) - [组件分类(内容扫描器)](#component-taxonomy-content-scanner) - [行为规则(运行时监控)](#behavior-rules-runtime-monitor) - [安装](#install) - [CLI](#cli) - [库 — 围绕 Agent 循环进行封装](#library--wiring-around-an-agent-loop) - [测试语料库](#test-corpus) - [运行测试](#run-the-tests) · [运行评估](#run-the-eval) - [仓库结构](#repository-layout) - [范围 / 非目标](#scope--non-goals) - [适用场景](#where-it-fits) - [许可证](#license) ## 为什么需要它 每个发布过 AI Agent 的团队都会面临同样令人不安的问题:*如果我的 Agent 读取的内容指示它执行我没有要求的操作,会发生什么?* 这就是间接提示注入,在过去的一年中,它已经从演示阶段发展为已记录的生产环境漏洞利用。对于防御者来说困难的部分在于:**所有这些都没有恶意软件哈希值** —— 这些都是对已修补漏洞的负责任的披露,因此唯一持久的“产物”就是攻击的*形态*。`ipi-detect` 就是围绕这种形态构建的。 ## 基于已记录、可归因的安全事件 每个恶意语料库样本和每个基于事件的规则都与一个真实的、已发布的攻击相关联,并带有主要来源和(如果存在)CVE —— 而不是手写的固定测试数据。请参阅 [`detections/THREAT_INTEL.md`](detections/THREAT_INTEL.md) 获取完整的证据库和分级。 | 事件 | CVE | 本仓库检测的内容 | |----------|-----|------------------------| | EchoLeak (M365 Copilot) | CVE-2025-32711 | 通过 CSP 信任的 Teams 代理进行 markdown-image 数据外泄 | | CamoLeak (GitHub Copilot Chat) | CVE-2025-59145 | 通过签名的 GitHub Camo 像素进行密钥外泄 | | AgentFlayer (ChatGPT Connectors) | — | 将 API-key 外泄至 Azure Blob 接收端 | | ShadowLeak (ChatGPT Deep Research) | — | 通过 `browser.open` 进行 base64 PII 外泄,利用安全措施框架 | | GitHub Copilot RCE | CVE-2025-53773 | 篡改 `autoApprove` 配置 (YOLO 模式) | | HashJack | — | URL fragment(在 `#` 之后)中的指令 | | GitHub MCP toxic flow | — | 私有仓库 → 公开 PR 数据外泄 | | Unit 42 / Forcepoint 真实环境 | — | 实时 IOC 域名 + 隐藏/意图模式 | 证据分级对产物非常诚实:零点击案例属于 **Tier A**( reputable 披露,无可检索的恶意软件/PoC —— 已修补漏洞披露),因此检测依赖于 payload *模式* 和行为 *流*,而不是哈希值。可运行的 MCP PoC 仓库和实时的供应商 IOC 域名属于 **Tier B**。 ## 双层架构 | 层级 | 模块 | 检查对象 | 捕获内容 | |-------|--------|----------|---------| | **内容扫描器** (pre-model) | `content_scanner.py` | 在到达模型*之前*从工具检索到的文本 | 结构化注入组件:权限伪装、指令性语言、强制准确性措辞、混淆、文档式框架 | | **行为监控** (runtime) | `behavior_monitor.py` | Agent 的工具调用序列 | 数据外泄*形态* —— 检索 → (编码/执行) → 携带编码数据的出站请求 —— 与 payload 的措辞无关 | | **集成防护** | `guard.py` | 两者,相关联 | 当摄取了可疑内容**并且** Agent 随后的行为表现得像是在遵循注入的指令时,升级为高置信度事件 | ## 威胁模型与检测覆盖率 (`detections/`) `detections/` 文件夹将完整的 IPI kill chain 映射到检测逻辑: - **[`ATTACK_TREE.md`](detections/ATTACK_TREE.md)** — 作为攻击树的六阶段 IPI kill chain(侦察 → 投递 → 越狱 → 摄取 → 行动 → 外泄),每种技术都标记为 `[C]` / `[B]` / `[C+B]` / `[GAP]` / `[PARTIAL]`,并附带一目了然的覆盖率表格和优先级差距列表。 - **[`rules.yml`](detections/rules.yml)** — 便携式 Sigma/YARA 风格检测规则,每种技术一条,每条都标记为 `implemented` 或 `gap`(差距规则带有用于填补它们的规范)。包括跨阶段上下文规则(升级、抑制引用)和集成的关联规则。 - **[`coverage_matrix.csv`](detections/coverage_matrix.csv)** — 机器可读的技术 → 信号 → 模块 → 状态映射。 - **[`verify_coverage.py`](detections/verify_coverage.py)** — 针对实时检测器执行每个 `implemented` 规则,如果任何声明没有代码支持则失败。在 CI 中运行它以保持文档的真实性: python detections/verify_coverage.py 目前的覆盖率:**34 条已实现的规则**(针对实时代码进行了验证),**13 条已记录的差距**。其余的差距分为模式族添加(编码解码后重新扫描、JSON 上下文中断、绕过审核、策略-DoS)和需要在此引擎上游使用 HTML/DOM 解析器或渲染+OCR 阶段的架构盲点(动态组装、属性填充、canvas/OCR 文本) —— 这些都已记录在案,以便部署环境可以通过扫描渲染后的 DOM 而不是原始 HTML 来进行补偿。 ## 为什么要双层架构 来源研究发现,**纯自然语言 payload** 可以击败内容层面的检测 —— 它们不包含任何结构性破绽。内容扫描器真实地反映了这一点:在捆绑的语料库评估中,它获得了 1.000 的精确率 / 0.933 的召回率,而漏检的恰好是这种 NL payload。行为监控器对其进行了兜底:NL payload 诱导的*行动*(携带检索数据 base64 的出站请求)无论措辞多么无害都是相同的,因此它会在运行时被捕获。 仅停留在内容层的防御在设计上就是可绕过的。这是本构建旨在编码的核心教训。 ## 基于真实环境遥测数据,而不仅仅是实验室 payload 检测器针对的是安全供应商在真实环境中实际观察到的内容,而不是纯粹的学术类别列表: - **Unit 42 (Palo Alto), "Fooling AI Agents"** — Web 投递占据主导地位:可见明文 (~38%)、HTML 属性伪装 (~20%)、CSS 隐藏 (~17%);社会工程学占越狱方法的 ~85%,而多语言仅占 ~2%。权重反映了这种分布(隐藏 + 指令得分高,多语言得分低)。 - **Forcepoint X-Labs, "10 IPI Payloads Caught in the Wild"** — 核心的现实世界检测问题:*用于检测 IPI 的触发短语与用于解释它的短语是相同的。* "Ignore previous instructions" 和 "If you are an LLM" 出现在博客文章和威胁情报报告中,因此简单的特征匹配必然会导致误报。他们的规则 —— 查看 **上下文:是否存在隐藏机制,以及该短语是作为祈使句针对 AI 发出的,还是作为示例引用的** —— 已被直接实现。 **上下文升级**机制是现实环境调优的核心: 1. 裸短语("ignore previous instructions", "reveal your system prompt")单独携带**几乎为零的权重**。 2. 只有当伴随着*隐藏*信号(CSS/markup 隐藏)或*条件性 AI 定向*("if you are an AI…")时,它们才会**急剧升级**。 3. 当文档读起来像是引用了该短语的安全文章("patterns such as…", "a common payload is…", "how to defend against…")并且没有任何隐藏内容时,**引用抑制**会将分数拉回。 结果:*完全相同*的短语当被隐藏在 `display:none` div 中时会被判为恶意,而在防御者的博客文章中被引用时则会被判为正常 —— 决定因素是上下文,而不是字符串。 ## 组件分类(内容扫描器) 反映了已发布的 IPI 研究和供应商遥测中观察到的类别: - **Authority** — `[SYSTEM]`, `[SYSTEM OVERRIDE]`, `---ADMIN NOTE---`, ``,魔法字符串/内部 token 欺骗,开发者/god mode,优先级覆盖框架 - **Framing** — 伪造的 `RUNBOOK.md` / `TASKFILE.yml`,合规检查/审计追踪/自动化框架 - **Directive** — `Required:`, `MUST:`,执行/运行命令语言 - **Accuracy** — "verbatim", "byte-for-byte", "no omissions" - **Obfuscation** — 解码后为文本的 base64 blob,零宽字符,混合脚本同形异义字 - **Concealment** (Web 投递) — `display:none`, `opacity:0`, `font-size:0`, 屏幕外定位,白底白字, `aria-hidden`/`visually-hidden`/`sr-only`,HTML 注释中的祈使句,`` 命名空间欺骗,`data-*` 指令属性,CDATA - **Conditional targeting** — "if you are an AI/LLM…",针对 AI 的注释,"human readers may ignore" - **Destructive** — `rm -rf`, `--no-preserve-root`,fork bombs,`DROP DATABASE`,资源耗尽重复 - **Payment** — PayPal.me / Stripe 链接,具体的金钱指令,订阅重定向 - **Multilingual** — 跨不同脚本重复相同的祈使句(根据遥测数据,权重较低) - **Extraction** (短语标记) — 裸露的 "ignore previous instructions" / "reveal your system prompt" 等,单独存在时权重几乎为零,仅在特定上下文中升级 - **Tool invocation / exfil hints** — 工具名称引用,工具调用 JSON 字面量,base64 接收端,带 query params 的 URL,数据外泄关键字 分数经过加权,并结合了**共现奖励**:几个不同组件组合在一起远比单独任何一个更具指示性,这与复杂的目标需要堆叠多个组件的发现相吻合。 扫描器还会规范化 Unicode 并重新检查**块分割**的内容,因为跨块分块的相同文本(例如 Notion 块)在模型看来可能与一个大块不同 —— 因此不能利用分块来绕过扫描器。 ## 行为规则(运行时监控) 与来源无关;基于观察到的动作和“taint”标志(一旦不可信内容进入上下文即被设置)进行推理: - `execute_after_retrieve` — 在不可信的检索之后运行 shell/code *(alert)* - `encoded_outbound` — 出站请求携带 base64 query param *(alert)* - `exfil_chain` — 在检索*之后*携带 base64 param 的出站请求 *(block)* - `exec_then_exfil` — 在检索之后执行并伴随出站请求 *(block)* - `private_host_outbound` — 检索后向 loopback/private host 发出的请求 *(watch)* - `csp_proxy_exfil` — 在检索后向已知的 CSP 信任的代理接收端 (Teams `asyncgw`, GitHub Camo, Azure Blob) 发出的携带数据的请求 *(block)* 工具分类可通过 `tool_classes` 进行配置,以匹配您的工具集。 ## 安装 ``` pip install -e . # from the project root ``` 没有第三方运行时依赖(仅使用标准库)。测试使用 `pytest`。 ## ``` # Scan a retrieved-content file (exit 0 clean, 1 not-clean) python -m ipi_detect.cli scan path/to/content.txt cat content.txt | python -m ipi_detect.cli scan - # Replay a tool-call trace (exit 0 none, 1 findings, 2 block) python -m ipi_detect.cli trace trace.json # Score the detector against the labeled corpus python -m ipi_detect.cli eval [corpus.json] # Check text for known in-the-wild IOC domains (Unit 42 + Forcepoint) python -m ipi_detect.cli ioc path/to/content.txt ``` `ioc` 命令针对 `ipi_detect/ioc_blocklist.py` 中捆绑的供应商 IOC 列表进行匹配(处理像 `example[.]com` 这样的去激活形式);`perceptivepumpkin.com` 被标记为在两份供应商报告中均被交叉引用。行为监控器还会阻止向已记录的 **CSP 信任的代理接收端**(Teams `asyncgw`, GitHub Camo, Azure Blob)进行出站/图像数据外泄,这些正是 EchoLeak、CamoLeak 和 AgentFlayer 所滥用的。 一个 trace 是一个 JSON 列表: ``` [{"name": "notion_search", "arguments": {"query": "..."}}, {"name": "fetch_web_page", "arguments": {"url": "http://localhost:8080/?d=QmFz..."}}] ``` ## 库 — 围绕 Agent 循环进行封装 ``` from ipi_detect import AgentGuard guard = AgentGuard(content_threshold=3.0) # 1. When a retrieval tool returns, scan BEFORE handing content to the model: scan = guard.inspect_retrieved(notion_page_text) # str or list[str] if scan.verdict() != "clean": notion_page_text = quarantine_or_annotate(notion_page_text) # 2. For each tool call the model wants to make, vet it first: findings = guard.inspect_tool_call("fetch_web_page", {"url": url}) if any(f.severity == "block" for f in findings): refuse(url) # veto the action # 3. At end of turn, get the correlated report: report = guard.finalize() print(report.summary()) ``` ## 测试语料库 `corpus/samples.json` 包含已标记的正常/恶意样本数据。恶意样本是用于检测测试的可识别的注入**形态** —— 而不是经过优化的、可用的绕过 payload。正常样本集特意包含了“硬负例”(合法的 runbook、YAML 任务文件、base64/RFC-4648 提及、`whoami` 文档),以真实反映误报情况。 使用您自己的样本扩展它并重新运行 `eval`,以便针对您的环境调整 `content_threshold` 和权重。 ## 运行测试 ``` python -m pytest tests/ -v ``` ## 运行评估 ``` python -m ipi_detect.cli eval # TP=14 FP=0 TN=14 FN=1 # precision=1.000 recall=0.933 f1=0.966 ``` 在良性硬负例中没有误报。按照设计,唯一漏检的是纯自然语言 payload,内容扫描器*应该*让其通过,而由行为层在运行时捕获。 ## 仓库结构 ``` ipi-detect/ ├── ipi_detect/ │ ├── content_scanner.py # pre-model content inspection │ ├── behavior_monitor.py # runtime tool-call monitoring │ ├── guard.py # integrated, correlated guard │ ├── ioc_blocklist.py # bundled vendor IOC domains │ └── cli.py # scan / trace / eval / ioc ├── detections/ │ ├── ATTACK_TREE.md # IPI kill chain → coverage │ ├── rules.yml # Sigma/YARA-style rules (implemented | gap) │ ├── coverage_matrix.csv # technique → signal → module → status │ ├── THREAT_INTEL.md # evidence base, tiered, with sources │ └── verify_coverage.py # CI check: claims must be backed by code ├── corpus/samples.json # labeled benign/malicious fixtures ├── tests/test_detect.py ├── demo/ # demo gif + capture/render scripts ├── BLOG.md # the write-up └── pyproject.toml ``` ## 范围 / 非目标 本项目用于检测和评分;它**不**生成、变异或优化注入 payload。它旨在用于蓝队对您自己的 Agent 进行评估:测量检测器的精确率/召回率并提供运行时防护。在依赖它之前,请针对您自己的流量调整阈值 —— 默认值是为捆绑的语料库设置的。在正式投入使用前,请对照 NVD 验证每个 CVE。 请记住更广泛的架构教训(Meta 的“Agents Rule of Two”):任何 agent 都不应*同时*处理不可信输入、访问敏感数据并更改外部状态。限制 agent 的操作范围比任何分类器都能更好地限制爆炸半径 —— 检测是第二道防线,而不是第一道。 ## 适用场景 与现有的社区工作保持一致,而不是重复造轮子:**OWASP LLM01:2025**、OWASP Prompt Injection Prevention cheat sheet、**Agent Threat Rules** 语料库、Microsoft Defender 的 `XPIADetected` 遥测,以及 Invariant 的 `mcp-scan`。将 `ipi-detect` 作为基础构建块 —— 围绕您的 agent 循环封装 `AgentGuard`,在模型看到检索到的内容之前对其进行扫描,并在每个工具调用执行之前对其进行审查。 ## 许可证 MIT。有关包元数据,请参见 `pyproject.toml`。 *由 [pjcampbe11](https://github.com/pjcampbe11) 维护。`ipi-detect` 是一款防御性工具:它用于检测和评分,不会生成或优化 payload。语料库重现了已发布的攻击模式以进行检测测试,而非可用的漏洞利用。*
标签:AI安全, AMSI绕过, Chat Copilot, DLL 劫持, LLM, Python, Unmanaged PE, 大语言模型, 威胁检测, 安全规则引擎, 提示词注入防御, 无后门, 逆向工具