静态分析工具,可扫描你的代码库以发现LLM提示注入和多模态安全漏洞。离线运行,无需API调用。
ContextHound 可贯穿你的整个开发和浏览工作流:
| 工具 | 功能 | 安装方式 |
|---|---|---|
| CLI / npm 包 | 扫描代码库中的提示注入漏洞。集成到 GitHub Actions,输出 SARIF、JSON、HTML 等格式。 | npm install -g context-hound |
| VS Code 扩展 | 编码时内联显示发现结果、代码操作、输出通道、状态栏。 | VS Code 市场 |
| 浏览器扩展 | 在任何 AI 聊天界面上实时显示扫描药丸,DevTools 面板用于 LLM API 流量,弹出式扫描器。支持 Chrome 和 Firefox。 | Firefox:免费安装 · Chrome:等待审核 · 源代码 |
随着基于 LLM 的应用在生产代码库中变得常见,提示注入已成为最具可攻击性的攻击面之一;而大多数安全扫描工具对此并无感知。
ContextHound 为你的提示层带来静态分析:
它可以作为 CLI 命令、npm 脚本或 GitHub Action 融入你现有的工作流,且没有任何外部依赖。
全局安装 —— 将 hound 命令添加到你的 PATH:```bash
npm install -g context-hound
**项目级安装** — 限定于单个仓库,通过 `npx hound` 或 npm 脚本运行:```bash
npm install --save-dev context-hound
Zero-install — 无需安装,直接使用缓存的npm注册表副本:```bash npx context-hound scan --dir .
## 快速开始```bash
# Scaffold a config file
hound init
# Scan your project
hound scan --dir ./my-ai-project
# Or via npm script (scans current directory)
npm run hound
# Verbose output, shows remediations and confidence levels
hound scan --verbose
# Fail the build on any critical finding
hound scan --fail-on critical
# Export JSON and SARIF reports
hound scan --format console,json,sarif --out results
# GitHub Annotations (for CI step summaries)
hound scan --format github-annotations
# Markdown report with findings tables
hound scan --format markdown --out report
# Stream findings as JSONL (one JSON object per line)
hound scan --format jsonl | jq '.severity'
# List all rules
hound scan --list-rules
# Explain a rule (or a rule family by prefix)
hound explain INJ-001
hound explain PST --format json
# Fast PR gate — scan only files changed vs. origin/main
hound scan --diff
# Interactive HTML report (self-contained, open in browser)
hound scan --format html --out report
# Re-scan on file changes
hound scan --watch
# Parallel scanning (default is 8; tune for your machine)
hound scan --concurrency 16
# Disable incremental cache for a clean run
hound scan --no-cache
# Baseline mode — only report findings new since the last saved scan
hound scan --format json --out baseline # save a baseline
hound scan --baseline baseline.json # compare future scans against it
# Load a custom rule from a local plugin file
hound scan # plugin declared in .contexthoundrc.json "plugins" field
# Only run high-confidence rules
hound scan --config .contexthoundrc.json # set minConfidence: "high"
# Fail if any single file scores >= 40
hound scan --fail-file-threshold 40
退出码:
| 代码 | 含义 |
|---|
添加到你的工作流中,当提示风险过高时阻止合并:```yaml
name: Prompt Audit
on: [push, pull_request]
jobs: hound: runs-on: ubuntu-latest permissions: contents: read security-events: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm install -g context-hound
- run: hound scan --format console,sarif,github-annotations --out results.sarif
- name: Upload to GitHub Code Scanning
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
发现结果将显示在你的仓库的 **Security > Code scanning** 标签页中。`github-annotations` 格式会在 PR 中发布内联评论,并将摘要表格写入 GitHub 步骤摘要。
---
## 配置
运行 `hound init` 来生成一个 `.contexthoundrc.json` 文件,或手动创建一个:```json
{
"include": ["**/*.ts", "**/*.js", "**/*.py", "**/*.go", "**/*.rs", "**/*.md", "**/*.txt", "**/*.yaml"],
"exclude": [
"**/node_modules/**",
"**/dist/**",
"**/tests/**",
"**/attacks/**"
],
"threshold": 60,
"formats": ["console", "sarif"],
"out": "results",
"verbose": false,
"failOn": "critical",
"maxFindings": 50,
"excludeRules": ["JBK-002"],
"includeRules": [],
"minConfidence": "medium",
"failFileThreshold": 80,
"concurrency": 8,
"cache": true,
"plugins": ["./rules/my-custom-rule.js"],
"baseline": "./baseline.json"
}
所有关键设置都可以在运行时覆盖,无需编辑配置文件:
.houndignore在项目根目录放置一个 .houndignore 文件,无需编辑 .contexthoundrc.json 即可添加排除模式。遵循相同的 glob 语法;以 # 开头的行是注释。
直接在源代码中静默已知的误报——无需在全局范围内禁用规则。指令可在任何文件类型中识别(周围的注释语法无关紧要):```ts
// hound-disable-next-line INJ-001 -- userInput is a validated enum
const prompt = Summarise the ${userInput} report;
const cmd = run(${shell}); // hound-disable-line CMD-001
// hound-disable RAG-007 -- trusted internal corpus only context.push(doc.metadata.title); context.push(doc.metadata.author); // hound-enable RAG-007
- `hound-disable-line [RULE...]` — 抑制同一行的发现
- `hound-disable-next-line [RULE...]` — 抑制下一行的发现
- `hound-disable [RULE...]` … `hound-enable [RULE...]` — 抑制一个块(在文件末尾自动关闭)
- 省略规则ID以抑制该位置的所有规则;列出一个或多个(空格/逗号分隔)以限定范围
- `--`之后的文本是自由格式的理由,会在报告中显示
运行 `--report-unused-suppressions` 以列出不再匹配任何发现的指令,以便清理无效的抑制:```bash
hound scan --report-unused-suppressions
使用 --preset 启用一个精选的子集规则,而不是列出 ID。预设会与你已有的任何 includeRules 联合,且可以组合多个预设:```bash
hound scan --preset owasp-llm-top10
hound scan --preset mcp,agentic
hound scan --list-presets # show all presets and their rule patterns
| 预置规则集 | 规则 |
|--------|-------|
| `owasp-llm-top10` | INJ, JBK, EXF, OUT, RAG, TOOL, SCH, DOS, VIS |
| `injection` | INJ, RAG, ENC |
| `jailbreak` | JBK |
| `exfiltration` | EXF |
| `agentic` | AGT, MCP, TOOL |
| `mcp` | MCP |
| `supply-chain` | SCH |
| `prompt-files` | INJ, JBK, EXF, ENC, SKL |
### pre-commit 钩子
ContextHound 提供了一个 [pre-commit](https://pre-commit.com) 钩子。将其添加到你的 `.pre-commit-config.yaml` 文件中:```yaml
repos:
- repo: https://github.com/IulianVOStrut/ContextHound
rev: v2.0.0
hooks:
- id: contexthound
# optional — scan only changed files and fail on high-severity findings:
# args: ["--diff", "HEAD", "--fail-on", "high"]
任何导出 Rule 或 Rule[] 的 .js 文件都可以作为插件加载:```js
// my-rule.js
module.exports = {
id: 'CUSTOM-001',
title: 'Proprietary data pattern in prompt',
severity: 'high',
confidence: 'high',
category: 'injection',
remediation: 'Remove internal identifiers from prompts.',
check(prompt) {
if (prompt.text.includes('INTERNAL_PATTERN')) {
return [{ evidence: 'INTERNAL_PATTERN', lineStart: 1, lineEnd: 1 }];
}
return [];
},
};
在 `.contexthoundrc.json` 中引用它:```json
{ "plugins": ["./my-rule.js"] }
插件规则与内置规则一样,受到相同的 excludeRules、includeRules 和 minConfidence 过滤器约束。
在初次扫描后保存基线,然后在后续扫描中仅报告新增的发现项:```bash
hound scan --format json --out baseline
hound scan --baseline baseline.json
发现结果通过 `ruleId + file` 匹配 —— 行迁移不会导致虚假的新发现告警。
### 仅变更文件(`--diff`)
为了快速的拉取请求门控,只扫描相对于某个 git 引用发生变更的文件,而不是整棵树:```bash
hound scan --diff # vs. origin/main (default)
hound scan --diff main # vs. a named branch
hound scan --diff HEAD~5 # vs. an arbitrary ref
涵盖已提交、暂存、未暂存以及未跟踪但未被忽略的文件。如果 git 不可用或引用无法解析(例如浅层 CI 克隆),ContextHound 会打印警告并回退到完整扫描,而不是静默通过。结合 --baseline 进行发现级别的差异比较,或单独使用 --diff 以获得最快的 PR 反馈。
每个发现都携带按以下方式计算的 风险分值:``` risk_points = severity_weight × confidence_multiplier
分数累加,上限为100,并按以下分级:
| 得分 | 等级 | 建议操作 |
|-------|-------|-----------------|
| 0-29 | 🟢 低 | 无需操作 |
| 30-59 | 🟡 中 | 合并前审查 |
| 60-79 | 🟠 高 | 合并前修复 |
| 80-100 | 🔴 严重 | 阻止部署 |
如果你的提示包含明确的安全语言(输入分隔符、拒绝揭示指令、工具允许列表),则该提示的风险分数将按比例降低。
---
## 规则
### A. 注入 (INJ)
| ID | 严重程度 | 描述 |
|----|----------|-------------|
| INJ-001 | 高 | 用户输入直接拼接到提示中,未使用分隔符 |
| INJ-002 | 中 | 缺少“将用户内容视为数据”的边界语言 |
| INJ-003 | 高 | 检索/检索到的上下文未使用不可信分隔符直接包含 |
| INJ-004 | 高 | 用户内容可覆盖工具使用指令 |
| INJ-005 | 高 | 序列化的用户对象(`JSON.stringify`)直接插入到提示模板中 |
| INJ-006 | 中 | 用户可控内容中的HTML注释包含隐藏指令动词 |
| INJ-007 | 中 | 用户输入包裹在代码块分隔符中,但未先去除反引号 |
| INJ-008 | 高 | HTTP请求数据(`req.body`、`req.query`、`req.params`)插入到`role: "system"`模板字符串中 |
| INJ-009 | 严重 | HTTP请求体直接解析为消息数组——攻击者控制角色和内容 |
| INJ-010 | 高 | 使用不可信输入拼接构建纯文本角色标签转录(`User:`、`Assistant:`、`system:`) |
| INJ-011 | 高 | 浏览器DOM或URL来源(`window.location`、`document.cookie`、`getElementById`)直接传入LLM调用 |
| INJ-012 | 高 | 对话历史未经清理直接展开到消息数组中 |
| INJ-013 | 高 | 工具/函数调用结果未经清理插入到消息中 |
| INJ-014 | 高 | LLM补全结果作为用户角色内容注入到后续LLM调用中 |
| INJ-015 | 高 | 不受信任的外部输入(HTTP/CLI/DOM)流入提示——与名称无关的**污点分析**,追踪别名,尊重清理器 |
### B. 数据泄露 (EXF)
| ID | 严重程度 | 描述 |
|----|----------|-------------|
| EXF-001 | 严重 | 提示引用了密钥、API密钥或凭证 |
| EXF-002 | 严重 | 提示指示模型揭示系统提示或隐藏指令 |
| EXF-003 | 高 | 提示表明可访问机密或私有数据 |
| EXF-004 | 高 | 提示包含内部URL或基础设施主机名 |
| EXF-005 | 高 | 敏感变量(令牌、密码、密钥)以Base64编码形式输出 |
| EXF-006 | 高 | 完整提示或消息数组通过`console.log` / `logger.*`记录而未进行脱敏 |
| EXF-007 | 严重 | 实际机密值嵌入提示中,同时附带“永不揭示”指令 |
### C. 越狱 (JBK)
| ID | 严重程度 | 描述 |
|----|----------|-------------|
| JBK-001 | 严重 | 检测到已知越狱短语(“忽略指令”、“DAN”等) |
| JBK-002 | 高 | 措辞薄弱的安全声明(“始终遵守”、“无论如何”) |
| JBK-003 | 高 | 角色扮演逃生舱口破坏了安全约束 |
| JBK-004 | 高 | 智能体被指示在未经确认或人类审查的情况下行动(“自动执行”、“无需确认”) |
| JBK-005 | 高 | 证据擦除或清除痕迹指令(“删除日志”、“不留痕迹”) |
| JBK-006 | 高 | 策略合法性框架与不安全操作请求结合(“作为渗透测试人员,提升权限”) |
| JBK-007 | 高 | 模型身份欺骗——声称是不同的AI模型,并结合安全绕过指令 |
| JBK-008 | 高 | 提示压缩攻击——指示压缩或总结系统提示 |
| JBK-009 | 高 | 嵌套指令注入——命令性指令包裹在“安全/无害的总结/翻译”框架中 |
### D. 不安全工具使用 (TOOL)
| ID | 严重程度 | 描述 |
|----|----------|-------------|
| TOOL-001 | 严重 | 无界工具执行(“运行任何命令”、“浏览任何地方”、反引号shell替换) |
| TOOL-002 | 中 | 工具使用描述中没有允许列表或使用策略 |
| TOOL-003 | 高 | 提及代码执行但未指定沙箱约束 |
| TOOL-004 | 严重 | 工具描述或模式字段来源于用户控制的变量 |
| TOOL-005 | 严重 | 工具`name`或端点`url`来源于用户控制的输入(`req.body`、`req.query`等) |
### E. 命令注入 (CMD)
检测AI工具周围代码中的易受攻击模式,其中成功的提示注入可升级为完整命令执行。受Google Gemini CLI中由Cyera Research Labs(2025年)发现的真实CVE启发。
| ID | 严重程度 | 描述 |
|----|----------|-------------|
| CMD-001 | 严重 | Shell命令使用未清理的变量插值构建——JS/TS(`execSync(\`cmd ${var}\``)、Python(`subprocess.run(f"cmd {var}")`)、PHP(`shell_exec($var)`)、Go(`exec.Command` + `fmt.Sprintf`)、Rust(`Command::new` + `format!`) |
| CMD-002 | 高 | 不完整的命令替换过滤:阻止`$()`但不阻止反引号,或反之 |
| CMD-003 | 高 | 来自`glob.sync`或`readdirSync`的文件路径未经清理直接用于shell命令 |
| CMD-004 | 严重 | Python `subprocess.run`/`subprocess.call`带`shell=True`并使用变量或f-string命令参数调用 |
| CMD-005 | 严重 | PHP `shell_exec`、`system`、`passthru`、`exec`或`popen`使用`$variable`参数调用 |
### F. RAG投毒 (RAG)
检测检索增强生成流水线中的架构错误,这些错误允许检索或摄入的内容覆盖系统级指令。
| ID | 严重程度 | 描述 |
|----|----------|-------------|
| RAG-001 | 高 | 检索或外部内容被分配到消息数组中的`role: "system"` |
| RAG-002 | 高 | 在文档摄入循环中检测到类似指令的短语(“system prompt:”、“always return”、“never redact”) |
| RAG-003 | 高 | 智能体记忆存储直接由用户控制输入写入,未经验证 |
| RAG-004 | 中 | 提示指示模型将检索到的上下文视为最高优先级,覆盖开发者指令 |
| RAG-005 | 中 | 无来源的检索——未检查来源元数据就将块插入提示 |
| RAG-006 | 高 | 检索进入提示前未应用ACL或信任层级过滤器 |
### G. 编码 (ENC)
检测基于编码的注入和规避技术,其中使用Base64或类似编码绕过基于字符串的过滤器。
| ID | 严重程度 | 描述 |
|----|----------|-------------|
| ENC-001 | 中 | 在提示构建附近对用户控制变量调用`atob`、`btoa`或`Buffer.from(x, 'base64')` |
| ENC-002 | 高 | 在指令关键词附近检测到隐藏的Unicode控制字符(零宽空格、双向覆盖) |
### H. 输出处理 (OUT)
涵盖LLM流水线的输出端——应用程序如何使用模型响应。不安全的消费可将提示注入载荷转化为应用程序级漏洞。
| ID | 严重程度 | 描述 |
|----|----------|-------------|
| OUT-001 | 严重 | 对LLM输出调用`JSON.parse()`(JS/TS)或`json.loads()`(Python),但未进行模式验证(Zod、AJV、Joi、Pydantic、Marshmallow等) |
| OUT-002 | 严重 | LLM生成的Markdown或HTML未经DOMPurify或等效清理器渲染 |
| OUT-003 | 严重 | LLM输出直接用作`exec()`、`eval()`或`db.query()`的参数 |
| OUT-004 | 严重 | Python `eval()`或`exec()`以LLM生成的输出作为参数调用 |
### I. 多模态 (VIS)
涵盖视觉、音频/视频和OCR流水线特有的信任边界违规。多模态输入是新兴的注入向量:攻击者控制图像URL、音频文件或扫描文档,可使用这些规则的模式将指令潜入模型。
| ID | 严重程度 | 描述 |
|----|----------|-------------|
| VIS-001 | 严重 | 用户提供的图像URL或base64数据未经域名或MIME验证直接转发给视觉API(gpt-4o、Claude 3、Gemini Vision) |
| VIS-002 | 严重 | 在构建视觉API消息的文件中,使用用户控制的路径调用`fs.readFile`/`readFileSync`——通过多模态输入的路径遍历 |
| VIS-003 | 高 | 音频/视频转录输出(Whisper、AssemblyAI、Deepgram等)未经清理直接输入提示消息——通过音频源的RAG投毒 |
| VIS-004 | 高 | OCR输出(Tesseract、Google Vision)被插入到`role: "system"`消息或系统提示变量中 |
### J. 技能市场 (SKL) — v1.1
针对OpenClaw `SKILL.md`文件和`skills/`目录中的任何markdown文件。触发条件包括:自我授权攻击、远程技能加载、注入指令、不安全命令分发、敏感路径访问、权限提升声明以及YAML前置元数据中的硬编码凭证。
| ID | 严重程度 | 描述 |
|----|----------|-------------|
| SKL-001 | 严重 | 技能正文指示智能体编写或修改其他技能文件——自我授权攻击,可在智能体重启后持续存在 |
| SKL-002 | 严重 | 技能正文指示智能体从外部URL获取或加载技能——允许攻击者在安装后更改技能行为 |
| SKL-003 | 严重 | 技能正文包含针对智能体核心指令的提示注入短语(“ignore previous instructions”、“you are now unrestricted”等) |
| SKL-004 | 高 | 技能前置元数据使用`command-dispatch: tool`和`command-arg-mode: raw`——将原始用户输入直接转发给工具,绕过模型安全推理 |
| SKL-005 | 高 | 技能正文引用敏感文件系统路径(`~/.ssh`、`~/.env`、`/etc/passwd`、`../../`)供智能体读取并可能泄露 |
| SKL-006 | 高 | 技能正文声称拥有提升的权限,或指示智能体覆盖或禁用其他已安装的技能 |
| SKL-007 | 严重 | 在YAML前置元数据中发现硬编码凭证值(API密钥、令牌、密码)——暴露给任何接收或安装该技能的人 |
| SKL-008 | 严重 | 心跳C2——技能定期调度远程获取,在干净安装后静默覆盖自身指令 |
| SKL-009 | 严重 | 智能体身份否认——技能指示智能体否认自己是AI,声称是人类,或采用欺骗性人格 |
| SKL-010 | 严重 | 反扫描器规避——技能包含专门设计用于误导安全审计工具的文字 |
| SKL-011 | 严重 | SOUL.md / IDENTITY.md 持久化——技能将指令写入智能体身份文件,这些文件在卸载后仍然存在 |
| SKL-012 | 高 | 自我复制蠕虫——技能指示智能体通过SSH或`curl\|bash`传播到可达主机 |
| SKL-013 | 高 | 自主金融交易——技能执行加密货币交易或持有私钥,而无需每次交易的用户确认 |
> **扫描OpenClaw技能:** 运行 `npx hound scan --dir ./skills` 或将 `**/skills/**/*.md` 和 `**/SKILL.md` 添加到 `include` 配置中。ContextHound 自动将技能文件以 `code-block` 形式输出,便于多行规则分析。
### K. 智能体 (AGT) — v1.3 / v1.9
针对多步智能体系统特有的风险:无界执行循环、未经验证的内存写入、用户输入泄露到智能体规划、智能体间信任边界违规以及OWASP智能体AI安全问题(ASI)的缺口。
| ID | 严重程度 | 描述 |
|----|----------|-------------|
| AGT-001 | 严重 | 工具调用参数接收系统提示内容——`tool_call`/`function_call`参数值包含`system:`或`instructions:`字段内容 |
| AGT-002 | 高 | 智能体循环未设置迭代或超时保护——智能体配置或代码中无 `max_iterations`、`max_steps`、`max_turns`、`timeout` 或 `recursion_limit` |
| AGT-003 | 高 | 智能体内存由未经验证的LLM输出写入——`memory.save()`、`memory.add()` 或 `vectorstore.upsert()` 使用原始模型响应变量调用 |
| AGT-004 | 高 | 计划注入——用户输入直接插入到智能体规划、任务或目标提示中,未使用信任边界包装 |
| AGT-005 | 严重 | 智能体信任声明的身份而无需密码学验证——基于 `agentId`、`sender`、`source` 或 `from_agent` 字段做出信任决策,但未进行HMAC、JWT或共享密钥验证 |
| AGT-006 | 高 | 原始智能体输出未经验证直接链式输入到另一个智能体——`.run()`、`.invoke()` 或 `.generate()` 直接以另一个智能体的 `.output`/`.content`/`.result` 作为参数调用 |
| AGT-007 | 严重 | 智能体自我修改——智能体在运行时用LLM生成的内容重写自身的 `system_prompt`、`instructions` 或 `tools` 列表 |
| AGT-008 | 严重 | ASI03——智能体使用派生自LLM输出的值调用 `assumeRole`、`grantAccess` 或 `setPermissions`;通过提示注入实现权限提升 |
| AGT-009 | 高 | ASI04——智能体在运行时从变量路径或动态导入加载工具或插件,导致供应链替代 |
| AGT-010 | 高 | ASI07——原始智能体输出在未进行HMAC、JWT签名或模式验证的情况下通过 `send`/`route`/`dispatch` 转发给另一个智能体 |
| AGT-011 | 高 | ASI08——智能体计划步骤错误被静默捕获(无重新抛出,无错误状态标志);下游步骤基于错误或不完整状态继续执行 |
### L. MCP安全 (MCP) — v1.7 / v1.8
涵盖特定于模型上下文协议(Model Context Protocol)的信任边界和供应链风险。MCP引入了新的攻击面:工具描述、传输URL、事件载荷以及跨服务器共享状态都可能携带注入或权限提升载荷。
| ID | 严重程度 | 描述 |
|----|----------|-------------|
| MCP-001 | 严重 | MCP工具描述未经清理直接注入到LLM提示中——原始 `tool.description` 值用于 `role: "system"` 或 `messages.push()` |
| MCP-002 | 高 | MCP工具注册时使用动态名称或描述——`server.tool()` 的第一个参数是变量或模板字面量,允许在批准后实施 rug-pull 攻击 |
| MCP-003 | 高 | MCP sampling/createMessage 处理器无人工批准守卫——`setRequestHandler(CreateMessageRequestSchema)` 未包含 `requireHumanApproval`、`confirm` 或 `approve` 检查 |
| MCP-004 | 中 | MCP传输URL由变量构建——`SSEClientTransport` 或 `WebSocketClientTransport` 使用 `new URL(variable)` 而非静态字符串初始化 |
| MCP-005 | 高 | MCP stdio传输使用 `shell: true`——使命令字符串可进行shell插值,若任何参数由用户控制则可被注入 |
| MCP-006 | 严重 | MCP混淆代理——来自MCP请求的认证令牌未经重新验证直接转发给下游API;`Authorization` 头部值直接源自 `request.params`、`context` 或 `event` |
| MCP-007 | 高 | 跨MCP上下文投毒——共享/全局上下文存储从MCP输出写入,未进行哈希、签名或来源检查 |
| MCP-008 | 高 | MCP stdio传输命令从变量路径加载——`StdioClientTransport`/`StdioServerTransport` 的 `command:` 字段是变量而非静态字符串字面量 |
| MCP-009 | 高 | MCP会话ID用作认证决策时未进行过期检查——`sessionId`/`connectionId` 相等性比较未带 TTL、`expiresAt` 或 `isExpired` 守卫(重放攻击) |
| MCP-010 | 严重 | MCP传输事件载荷未经清理直接注入到LLM上下文中——事件/消息的 `.data`、`.content` 或 `.payload` 直接用于 `messages.push()` 或 `content:` 字段 |
---
## 示例输出```
=== ContextHound Prompt Audit ===
src/prompts/assistant.ts (file score: 73)
[HIGH] INJ-001: Direct user input concatenation without delimiter
File: src/prompts/assistant.ts:12
Evidence: Answer the user's question: ${userInput}
Confidence: medium
Risk points: 23
Remediation: Wrap user input with clear delimiters (e.g., triple backticks)
and label it as "untrusted user content".
[CRITICAL] EXF-001: Prompt references secrets, API keys, or credentials
File: src/prompts/assistant.ts:8
Evidence: The database password is: secret123.
Confidence: high
Risk points: 50
Remediation: Remove all secret values from prompts. Use environment
variables server-side; never embed credentials in prompt text.
────────────────────────────────────────────────────────
Repo Risk Score: 87/100 (CRITICAL)
Threshold: 60
Total findings: 5
By severity: critical: 2 high: 2 medium: 1
✗ FAILED - score meets or exceeds threshold.
src/ ├── cli.ts # CLI entry point (Commander.js) ├── types.ts # Shared TypeScript types ├── config/ │ ├── defaults.ts # Default include/exclude globs and settings │ └── loader.ts # .contexthoundrc.json loader + env var overrides ├── scanner/ │ ├── discover.ts # File discovery via fast-glob │ ├── extractor.ts # Prompt extraction (raw, code, structured) │ ├── languages.ts # LLM API trigger patterns per language extension │ ├── cache.ts # Incremental scan cache (.hound-cache.json) │ └── pipeline.ts # Orchestrates the full scan; parallel + cache + plugins ├── rules/ │ ├── types.ts # Rule interface and scoring helpers │ ├── injection.ts # INJ-* rules │ ├── exfiltration.ts # EXF-* rules │ ├── jailbreak.ts # JBK-* rules │ ├── unsafeTools.ts # TOOL-* rules │ ├── commandInjection.ts # CMD-* rules │ ├── rag.ts # RAG-* rules │ ├── encoding.ts # ENC-* rules │ ├── outputHandling.ts # OUT-* rules │ ├── multimodal.ts # VIS-* rules │ ├── skills.ts # SKL-* rules │ ├── agentic.ts # AGT-* rules │ ├── mcp.ts # MCP-* rules │ ├── supplyChain.ts # SCH-* rules │ ├── dos.ts # DOS-* rules │ ├── mitigation.ts # Mitigation presence detection │ └── index.ts # Rule registry ├── runtime/ │ ├── index.ts # createGuard() — runtime message inspection API │ ├── inspect.ts # Core inspection logic for live message arrays │ └── types.ts # RuntimeMessage, InspectResult, GuardConfig types ├── scoring/ │ └── index.ts # Risk score calculation and rule filtering └── report/ ├── console.ts # ANSI-coloured terminal output ├── json.ts # JSON report builder ├── sarif.ts # SARIF 2.1.0 report builder ├── githubAnnotations.ts# GitHub Actions annotation formatter ├── markdown.ts # Markdown report with findings tables ├── jsonl.ts # JSONL streaming formatter └── html.ts # Self-contained interactive HTML report attacks/ # Example injection strings (not executed against models) tests/ ├── fixtures/ # Sample prompts for testing ├── rules.test.ts # Unit tests for all rules ├── scoring.test.ts # Unit tests for scoring logic ├── scanner.test.ts # Integration tests for the scan pipeline ├── extractor.test.ts # Unit tests for prompt extraction ├── formatters.test.ts # Unit tests for all report formatters ├── mitigation.test.ts # Unit tests for mitigation detection └── cli.test.ts # CLI integration tests (init, list-rules, exit codes) .github/ ├── action.yml # Reusable composite GitHub Action └── workflows/ └── context-hound.yml # CI workflow
---
## 基准测试
ContextHound 附带了一个标记的基准测试数据集,用于衡量误报率和检测率。在构建后运行它:```bash
npm run benchmark
该基准测试扫描两个修复目录:
| 目录 | 目的 |
|---|---|
benchmarks/safe/ | 5 个包含真实安全模式的文件 — 预期 0 个发现 |
benchmarks/unsafe/ | 8 个包含真实漏洞的文件 — 每一条规则一个 |
v1.4.0 上的结果:``` File-level FP rate: 0.0% (0 / 5 safe files produced findings) Detection rate: 100.0% (8/8 expected findings triggered)
如果发现任何假阳性或假阴性,基准测试将以退出码1退出,这使其适合作为规则变更的CI质量门。要添加测试用例,请将文件放入`benchmarks/safe/`或`benchmarks/unsafe/`,并在`benchmarks/labels.json`中更新预期的发现结果。
### 每规则的精确率/召回率
基准测试还会打印一张**每规则信号表**(最差的F1排在前面),以便容易发现低精确率的规则——每个标记规则的真正/假阳性、假阴性、精确率、召回率和F1。假阳性计数来自`safe/`测试用例(真实情况:零发现);真正/假阴性来自标记的`unsafe/`测试用例。传递`--report <path>`参数还可以输出机器可读的JSON报告,用于仪表板或CI趋势跟踪:```bash
npm run benchmark -- --report bench-report.json
ContextHound 浏览器扩展为 Chrome 和 Firefox 带来实时提示注入检测。它使用与 CLI 相同的规则引擎,本地编译和打包——无需网络请求,没有后端。
状态: Firefox 扩展已上线——从 Firefox 附加组件安装。Chrome 提交正在等待 Web Store 审核。源代码位于 github.com/IulianVOStrut/ContextHound-Extensions。
扫描指示器 一个轻量级指示器出现在任何网站的任何 AI 聊天输入框旁边。当你输入时,扩展会根据 70 条检测规则扫描文本,并在下拉面板中显示风险评分和发现——无需页面导航。
DevTools 面板 打开浏览器 DevTools 并选择 ContextHound 标签页,实时监控 LLM API 流量。该扩展拦截发往 OpenAI、Anthropic、Google Gemini、Mistral、Groq、Cohere、DeepSeek 及其他服务的出站请求,扫描请求体和响应中的注入内容。工具栏徽章反映当前会话中看到的最高风险评分。
弹出式扫描器 点击工具栏图标,手动粘贴并扫描任何文本。适用于在使用前审查从第三方收到的提示或系统指令。
Chrome 和 Firefox 的 DevTools HAR API (onRequestFinished) 对于大多数 AI 聊天服务使用的流式/SSE 响应,并不可靠地包含请求体字节。该扩展通过两层方法解决这一问题:
chrome.webRequest.onBeforeRequest 在请求发送前拦截 service worker 中的原始请求字节,将其短暂缓存到 chrome.storage.session(TTL:5 分钟)。onRequestFinished 触发且 postData 不存在时,DevTools 页面通过 POP_BODY_CACHE 消息从 service worker 获取缓存的请求体。该扩展不收集任何用户数据。所有扫描均在本地进行。请参阅隐私政策。
欢迎贡献。要添加新规则:
src/rules/ 中的相应文件(或为新类别创建新文件)src/rules/index.ts 中注册它tests/rules.test.ts 中添加至少一个正面和一个负面测试用例npm test 以验证所有测试通过MIT
| 95 条安全规则 | 涵盖 14 个类别:注入、数据外泄、越狱、不安全工具使用、命令注入、RAG 投毒、编码、输出处理、多模态、技能市场、智能体、MCP、供应链、拒绝服务 |
| 数值风险评分(0-100) | 标准化的仓库级评分,带有低、中、高和严重阈值 |
| 缓解措施检测 | 提示中的显式安全用语会降低你的评分 |
| 7 种输出格式 | 控制台、JSON、SARIF、GitHub 注解、Markdown、JSONL 流式输出以及交互式 HTML |
| 内含 GitHub Action | 在风险高时使 CI 失败,并自动上传 SARIF 结果 |
| 多语言扫描 | 检测 Python、Go、Rust、Java、C#、PHP、Ruby、Swift、Kotlin、Vue、Bash 中的 LLM API 使用——不仅限于 TypeScript/JavaScript |
| 规则过滤 | 使用前缀 glob 语法(CMD-*)进行 excludeRules/includeRules;minConfidence 过滤器 |
| 增量缓存 | .hound-cache.json 在重新运行时跳过未更改的文件;--no-cache 禁用 |
| 插件系统 | 通过配置中的 "plugins": ["./my-rule.js"] 从本地 .js 文件加载自定义规则 |
| 基线 / 差异模式 | --baseline results.json —— 仅报告并失败于先前扫描中不存在的发现 |
| 观察模式 | --watch 在文件变更时重新扫描并显示差异发现 |
| 并行扫描 | 并发文件处理(--concurrency <n>,默认 8) |
| 完全离线 | 无 API 调用、无遥测、无付费依赖 |
0 | 通过 — 分数低于阈值,无 failOn 违规 |
1 | 未处理的错误或参数错误 |
2 | 阈值被突破 — 仓库分数 ≥ 阈值,或文件阈值超出 |
3 | --fail-on 违规 — 发现指定严重级别的结果 |
| 选项 | 默认值 | 描述 |
|---|
include | **/*.{ts,tsx,js,jsx,py,go,rs,java,kt,cs,php,rb,swift,vue,sh,bash,hs,md,txt,yaml,yml,json} | 要扫描的 Glob 模式 |
exclude | **/node_modules/**, **/dist/** 等 | 要忽略的 Glob 模式 |
threshold | 60 | 仓库评分达到或超过此值时失败(退出码 2) |
formats | ["console"] | 输出格式:console, json, sarif, github-annotations, markdown, jsonl, html |
out | 自动 | 文件输出的基础路径 |
verbose | false | 显示每个发现项的修复建议和置信度 |
failOn | 未设置 | 在首次发现 critical、high 或 medium 级别时退出码 3 |
maxFindings | 未设置 | 在发现 N 个项后停止 |
excludeRules | [] | 跳过指定规则 ID 或前缀 glob(例如 "CMD-*", "JBK-002") |
includeRules | [] | 仅运行这些规则 ID(空数组 = 运行所有规则) |
minConfidence | 未设置 | 跳过低于此置信度的规则:low、medium 或 high |
failFileThreshold | 未设置 | 任何单个文件评分达到或超过此值时失败(退出码 2) |
concurrency | 8 | 最多并行处理的文件数 |
cache | true | 启用增量扫描缓存(.hound-cache.json);设置为 false 或使用 --no-cache 可禁用 |
plugins | [] | 本地 .js 规则插件的路径;每个插件必须导出 Rule 或 Rule[] |
baseline | 未设置 | 旧 JSON 报告的路径;仅报告基线中不存在的发现项 |
| 变量 | 覆盖项 |
|---|
HOUND_THRESHOLD | threshold |
HOUND_FAIL_ON | failOn |
HOUND_MIN_CONFIDENCE | minConfidence |
HOUND_VERBOSE | verbose(真值:1、true、yes) |
HOUND_CONFIG | 配置文件路径 |