Humanbound Actions 将 Humanbound CLI 封装为 GitHub Action,让团队在 CI 流程中对 AI Agent 自动进行对抗性安全测试并作为质量门禁。
Humanbound Actions
每次 push 时对 AI agent 进行对抗性安全测试。
将 hb test 封装为 GitHub Action:
符合 OWASP 标准的对抗性与行为测试 — prompt injection、工具滥用、数据泄露等 —
测试结果将作为构建的门禁,并显示在 GitHub 的 Security 标签页中。
快速开始 ·
工作原理 ·
场景 ·
输入项 ·
文档
- **符合 OWASP 标准的对抗性测试** — 多轮 prompt injection、数据泄露、过度权限、工具滥用等;也可通过 `category` 进行行为/QA 测试([测试目录](https://docs.humanbound.ai/methodology/adversarial-engine/))
- **真正的质量门禁** — `fail-on: high` 会将发现的问题转化为红色构建(失败)
- **在 GitHub 的 Security 标签页中展示结果** — [原生 SARIF 输出](#security-tab-sarif)
- **在您的工作环境中展示结果** — 工作流运行页面提供严重性摘要,并以 artifact 形式提供完整的 JSON 文件
- **两种运行方式** — 本地模式(无需账号,使用您的 LLM key)或平台模式(结果展示在您的 Humanbound dashboard 中)
## 此仓库中的 Actions
| Action | 引用 | 功能 |
|--------|-----------|--------------|
| **Test** | `humanbound/actions@v1` | 作为 CI 门禁的对抗性安全测试 — 详见下文。 |
## 快速开始
在 job 中启动您的 agent,将 action 指向它,并在发现高危问题时使构建失败 — 使用本地模式,无需账号:
```
# .github/workflows/agent-security.yml
name: Agent security
on: [pull_request]
jobs:
security:
runs-on: ubuntu-latest
steps:
- run: docker compose up -d agent # start your agent, reachable on localhost
- uses: humanbound/actions@v1
with:
# Your agent's config — inline here; a file or a build step also work (see below)
endpoint: |
{
"streaming": null,
"chat_completion": {
"endpoint": "http://localhost:8000/chat",
"payload": { "content": "$PROMPT" }
}
}
provider-api-key: ${{ secrets.OPENAI_API_KEY }} # the attacker/judge LLM key
model: gpt-4.1
fail-on: high
```
该 action 会安装 Humanbound CLI,对您的 agent 发起攻击,如果发现 `high` 或更高等级的问题,则会使 job 失败。
## 工作原理
1. **您将其指向您的 agent。** `endpoint` 描述了如何调用它;`$PROMPT` 会在每次攻击消息中被替换。
2. **它运行对抗性测试。** Humanbound CLI 会生成多轮攻击 — 符合 OWASP 标准的 prompt injection、工具滥用、数据泄露等 — 并会逐步升级攻击强度。
3. **LLM 评估器对每个响应进行评分**,并记录问题及其严重性。
4. **测试结果作为构建门禁并展示在您的工作流中。** `fail-on` 设定退出代码,运行页面会显示严重性摘要,并且发现的问题可以作为 SARIF 流入 **Security 标签页**。
## 选择哪种模式?
Action 会根据您提供的凭证自动检测模式:
| | **本地模式** | **平台模式** |
| -------------------------- | --------------------------------- | ------------------------------------------------- |
| **凭证** | `provider-api-key`(您的 LLM key) | `api-key`(Humanbound 项目 key) |
| **引擎运行位置** | 在 runner 内部 | 在 humanbound.ai 上 |
| **谁访问您的 agent** | Runner(在 job 中启动它) | Humanbound 的服务器(需要公开的/用于预发布的 URL) |
| **攻击者/评估器 LLM** | CI 中的您的 key | 平台上配置的 provider |
| **是否需要账号** | 否 | 是(+ 一个项目) |
| **结果** | CI artifact + 运行摘要 | CI artifact + 运行摘要 + dashboard |
## 配置您的 agent (`endpoint`)
`endpoint` 输入项是您的 agent 的集成配置 — 它告诉测试 bot 如何调用您的 agent(`$PROMPT` 会被替换为每条攻击消息;回复可以是纯文本或 JSON,系统会自动检测常见的 content 字段)。您可以选择以下任一合适的形式提供:
- **内联 JSON** — 直接将配置粘贴到工作流中。适用于简单的配置,您可以在 auth header 中引用 `${{ secrets.* }}`。
- **在先前步骤中构建** — 在较早的 CI 步骤中渲染 JSON(例如使用 `jq`),然后传递文件路径。当配置需要保密或变得过大时最为适用 — 请参阅[将 agent 凭证保留在 secrets 中](#keep-agent-credentials-in-secrets)。
- **提交的文件** — 例如 `endpoint: ./bot-config.json`,签入您的代码仓库。没有 secrets 时这是最简单的方法。
这三种方式都会生成相同结构的 JSON:
```
{
"streaming": null,
"chat_completion": {
"endpoint": "http://127.0.0.1:8000/chat",
"headers": { "Authorization": "Bearer
" },
"payload": { "content": "$PROMPT" }
}
}
```
完整的配置参考 — payload 模板、用于无状态 agent 的 `$CONVERSATION`、流式/WebSocket agent、响应提取:[Agent 配置](https://docs.humanbound.ai/getting-started/agent-config/)。
# 场景
**本地模式**(目前可用,无需账号):
- [快速 PR 门禁](#quick-pr-gate)
- [将 agent 凭证保留在 secrets 中](#keep-agent-credentials-in-secrets)
- [让评估器了解您 agent 的范围](#teach-the-judge-your-agents-scope)
- [使用 Ollama 进行免费本地测试](#free-local-testing-with-ollama)
**平台模式**(即将推出 — [见上文](#which-mode)):
- [平台 PR 门禁](#platform-pr-gate)
- [针对您的项目测试预览部署](#test-a-preview-deployment-against-your-project)
**两种模式及混合设置:**
- [Security 标签页 (SARIF)](#security-tab-sarif)
- [选择测试类别](#choosing-a-test-category)
- [夜间深度扫描](#nightly-deep-scan)
- [将结果保留为 artifact](#keep-results-as-artifacts)
- [混合模式:PR 使用本地门禁,夜间使用平台进行深度扫描](#mixed-local-gate-on-prs-platform-depth-nightly)
## 本地模式
### 快速 PR 门禁
在 job 内部启动您的 agent,运行快速扫描(目前大约需要 20 分钟 — 目前 `quick` 是 `unit` 的 CLI 别名),在发现高危问题时使构建失败:
```
jobs:
security-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: docker compose up -d agent # or however your agent starts
- uses: humanbound/actions@v1
with:
# Inline config (recommended for a simple, secret-free agent).
# You can also build it in a step or commit a file — see below.
endpoint: |
{
"streaming": null,
"chat_completion": {
"endpoint": "http://localhost:8000/chat",
"payload": { "content": "$PROMPT" }
}
}
provider-api-key: ${{ secrets.OPENAI_API_KEY }}
model: gpt-4.1
level: quick
fail-on: high
```
在本地模式下,`localhost` 指的是 runner 本身,因此请在 job 中启动 agent(后台进程或 [service container](https://docs.github.com/en/actions/using-containerized-services/about-service-containers))。引擎完全在 runner 中运行 — 使用与平台相同的 orchestrator、攻击和评估器;有关其工作原理,请参阅[本地引擎](https://docs.humanbound.ai/local-engine/)。
### 将 agent 凭证保留在 secrets 中
如果您的 agent 需要验证,请不要提交包含 token 的 `bot-config.json` — 应该在 job 中生成配置并注入 secret。有两种等效的方法:
**内联 JSON**(`endpoint` 输入项直接接受 JSON,而不仅仅是路径):
```
- uses: humanbound/actions@v1
with:
endpoint: |
{
"streaming": null,
"chat_completion": {
"endpoint": "https://staging.my-agent.com/chat",
"headers": { "Authorization": "Bearer ${{ secrets.AGENT_TOKEN }}" },
"payload": { "content": "$PROMPT" }
}
}
provider-api-key: ${{ secrets.OPENAI_API_KEY }}
model: gpt-4.1
```
**或者在步骤中渲染文件** — 当 headers 增多时更易于阅读(`jq` 已预装在 runner 上,通过 `env:` 传递 secrets 可以避免它们出现在脚本文本中):
```
- name: Render agent config
env:
AGENT_URL: ${{ vars.AGENT_URL }}
AGENT_TOKEN: ${{ secrets.AGENT_TOKEN }}
run: |
jq -n --arg url "$AGENT_URL" --arg auth "Bearer $AGENT_TOKEN" \
'{streaming: null, chat_completion: {endpoint: $url,
headers: {Authorization: $auth}, payload: {content: "$PROMPT"}}}' \
> bot-config.json
- uses: humanbound/actions@v1
with:
endpoint: ./bot-config.json
provider-api-key: ${{ secrets.OPENAI_API_KEY }}
model: gpt-4.1
```
如果 secret 值出现在日志中,GitHub 会自动将其掩盖,并且该 action 永远不会打印配置内容。scope 文件很少需要这种处理 — 允许/受限的 intent 通常不是机密,将它们与 agent 一起进行版本控制是一项特性 — 但这种“渲染文件”的模式同样适用于 `scope:`,或者您也可以通过 `repo: .` / `system-prompt:` 提取完全跳过该文件。
### 让评估器了解您 agent 的范围
如果没有 scope,评估器只有通用的安全预期。告诉它您的 agent _应该_ 做什么,可以产生有针对性的攻击,并大大减少误报 — “agent 处理了退款”对于天气 bot 来说是一个问题,但对于支持 bot 来说却是正常行为。有三种方法,按精确度从高到低排列:
```
# 1. 显式 scope 文件 — 最精确
- uses: humanbound/actions@v1
with:
endpoint: ./bot-config.json
provider-api-key: ${{ secrets.OPENAI_API_KEY }}
model: gpt-4.1
scope: ./scope.yaml
# 2. 扫描已检出的 repo 以查找 system prompts 和 tool definitions
- uses: humanbound/actions@v1
with:
endpoint: ./bot-config.json
provider-api-key: ${{ secrets.OPENAI_API_KEY }}
model: gpt-4.1
repo: .
# 3. 直接指向 system prompt 文件
- uses: humanbound/actions@v1
with:
endpoint: ./bot-config.json
provider-api-key: ${{ secrets.OPENAI_API_KEY }}
model: gpt-4.1
system-prompt: ./prompts/system.txt
```
scope 文件列出了允许和受限的 intent。请注意,`scope` **只能是文件路径** — 与 `endpoint` 不同,它不接受内联内容,因此您要么提交该文件,在步骤中渲染它,要么使用上面提到的 `repo:` / `system-prompt:` 发现机制完全跳过它:
```
# scope.yaml
business_scope: 'Customer support for Acme Bank'
permitted:
- Provide account balance and transaction info
- Process routine transfers within limits
restricted:
- Close accounts directly
- Access internal system records
```
`context` 输入项会在任何 scope 来源之上添加特定于运行的评估器上下文 — 例如 `context: 'Authenticated as Alice, her PII is expected'` 可以在经过身份验证的测试会话中阻止“泄露了 Alice 的数据”这种误报。完整详情:[范围发现](https://docs.humanbound.ai/local-engine/scope-discovery/)。
这三个 scope 输入项**仅限本地模式** — 在平台模式下,scope 是在您运行 `hb connect` 时在项目上捕获的(如果您在其中设置它们,action 会发出警告)。`context` 在两种模式下均可使用。
### 使用 Ollama 进行免费本地测试
无需付费的 LLM key:在 job 内部使用 Ollama 运行攻击者/评估器。这适用于 GitHub 托管的 runner,但需要提醒您:它们仅支持 CPU(在 `ubuntu-latest` 上为 4 vCPU),因此请使用**小模型**,并预期扫描时间会比使用云 provider 长得多 — 而且[本地模型生成的攻击质量较低](https://docs.humanbound.ai/local-engine/provider-config/))。这适合零成本的冒烟覆盖;对于严格的安全扫描,请使用云端 key 或带有 GPU 的自托管 runner。
```
- name: Start Ollama
run: |
curl -fsSL https://ollama.com/install.sh | sh
# The installer starts the server (systemd) on GitHub runners; start it
# ourselves only if it isn't up, then wait until the API answers.
pgrep -x ollama >/dev/null || (ollama serve &)
for i in $(seq 1 30); do curl -sf http://127.0.0.1:11434/ >/dev/null && break; sleep 1; done
ollama pull llama3.2:3b
- uses: humanbound/actions@v1
with:
endpoint: ./bot-config.json
provider: ollama
provider-api-key: unused # ollama needs no key; any value selects local mode
model: llama3.2:3b
provider-endpoint: http://127.0.0.1:11434
```
## 平台模式
适用于 [humanbound.ai](https://humanbound.ai) 上的团队:引擎在服务器端运行(CI 中无需 LLM key),结果会连同完整的实验历史记录一起显示在您的 dashboard 中。只需在您的终端进行一次性设置 — [`hb connect --endpoint ./bot-config.json`](https://docs.humanbound.ai/getting-started/quick-start/#step-2-connect-your-agent) 会创建项目、提取 scope 并存储您的 agent 配置 — 然后将项目的 API key 复制到仓库 secret 中。
因为引擎运行在 humanbound.ai 上,所以必须可以从互联网访问您的 agent(预发布或生产 URL)— 在 job 中启动的 `localhost` agent 在平台模式下不起作用;这种情况请使用本地模式。
### 平台 PR 门禁
```
- uses: humanbound/actions@v1
with:
api-key: ${{ secrets.HUMANBOUND_API_KEY }}
# endpoint optional — defaults to the project's stored integration
level: quick
fail-on: high
```
无需 checkout,无需启动 agent,无需 LLM key:项目已经知道如何访问您的 agent,并且每次运行都会与您的测试历史记录一起显示在 dashboard 中。
### 针对您的项目测试预览部署
平台模式下的 `endpoint` 会针对该运行_覆盖_项目存储的集成配置 — 使用相同的项目历史,但目标不同。适用于针对每个 PR 的预览环境:
```
- uses: humanbound/actions@v1
with:
api-key: ${{ secrets.HUMANBOUND_API_KEY }}
endpoint: |
{
"streaming": null,
"chat_completion": {
"endpoint": "https://pr-${{ github.event.number }}.preview.example.com/chat",
"headers": {},
"payload": { "content": "$PROMPT" }
}
}
level: quick
fail-on: high
```
## 两种模式及混合设置
### Security 标签页 (SARIF)
测试结果会按严重性分级和 PR 标注显示在 **Security → Code scanning** 中。添加上传步骤及其权限:
```
permissions:
contents: read
security-events: write # required to upload SARIF
steps:
- uses: actions/checkout@v4
- uses: humanbound/actions@v1
id: hb
with:
endpoint: ./bot-config.json
provider-api-key: ${{ secrets.OPENAI_API_KEY }}
model: gpt-4.1
fail-on: '' # report-only, so findings land as alerts, not red builds
- uses: github/codeql-action/upload-sarif@v3
# the != '' check matters: on an early failure the action has no SARIF to
# output, and upload-sarif hard-fails on an empty sarif_file input
if: always() && steps.hb.outputs.sarif-file != ''
with:
sarif_file: ${{ steps.hb.outputs.sarif-file }}
```
Humanbound 的发现结果是会话级别的,而不是行级别的,因此(就像容器和依赖项扫描器一样)每个告警都锚定到一个文件 — 如果您的 agent 配置在仓库中,则是该配置文件;否则为工作流文件。设置 `sarif-file: ""` 可以完全禁用 SARIF。
### 选择测试类别
三种内置的测试引擎(orchestrator),通过 `category` 选择:
| Category | 功能 | 使用场景 |
| ------------------------------------------------ | ------------------------------------------------------------- | ------------------------------ |
| `humanbound/adversarial/owasp_agentic` (默认) | 具有分数引导升级的多轮对抗性攻击 | 主要的安全门禁 |
| `humanbound/adversarial/owasp_single_turn` | 以最大强度进行的单提示攻击 — 快速、量大 | 快速、广泛的覆盖范围 |
| `humanbound/behavioral/qa` | Intent 边界、响应质量、功能正确性 | “agent 是否保持在任务上?” |
```
- uses: humanbound/actions@v1
with:
endpoint: ./bot-config.json
provider-api-key: ${{ secrets.OPENAI_API_KEY }}
model: gpt-4.1
category: humanbound/behavioral/qa
fail-on: medium
```
有关各引擎工作原理的更多信息:[Orchestrator](https://docs.humanbound.ai/local-engine/orchestrators/)。
### 夜间深度扫描
在 PR 上使用快速门禁;在计划任务中使用更深层次的级别:
```
on:
pull_request:
schedule:
- cron: '0 3 * * *'
jobs:
security-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: docker compose up -d agent
- uses: humanbound/actions@v1
with:
endpoint: ./bot-config.json
provider-api-key: ${{ secrets.OPENAI_API_KEY }}
model: gpt-4.1
level: ${{ github.event_name == 'schedule' && 'system' || 'quick' }}
fail-on: high
```
### 将结果保留为 artifact
```
- uses: humanbound/actions@v1
id: hb
with:
endpoint: ./bot-config.json
provider-api-key: ${{ secrets.OPENAI_API_KEY }}
model: gpt-4.1
- uses: actions/upload-artifact@v4
if: always() && steps.hb.outputs.results-file != ''
with:
name: security-results
path: ${{ steps.hb.outputs.results-file }}
```
### 混合模式:PR 使用本地门禁,夜间使用平台进行深度扫描
这两种模式互为补充:本地模式测试您在 job 中启动的临时 agent(快速反馈,无需公共 endpoint);平台模式在夜间测试您的预发布部署,结果会累积在 dashboard 中。
```
on:
pull_request:
schedule:
- cron: '0 3 * * *'
jobs:
pr-gate:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: docker compose up -d agent
- uses: humanbound/actions@v1
with:
endpoint: ./bot-config.json
provider-api-key: ${{ secrets.OPENAI_API_KEY }}
model: gpt-4.1
level: quick
fail-on: high
nightly-platform:
if: github.event_name == 'schedule'
runs-on: ubuntu-latest
steps:
- uses: humanbound/actions@v1 # platform mode: coming soon
with:
api-key: ${{ secrets.HUMANBOUND_API_KEY }}
level: system
fail-on: high
```
# 推荐权限
该 action 本身不需要特殊权限。它周围的 job 需要:
```
permissions:
contents: read # checkout
security-events: write # only if uploading SARIF to the Security tab
```
# 输入项
除了凭证(本地模式使用 `provider-api-key` **或**平台模式使用 `api-key`)以及本地模式下的 `endpoint` 之外,其他所有参数都是可选的。
| Input | 模式 | 描述 | 默认值 |
|-------|------|-------------|---------|
| `provider-api-key` | 本地 | 攻击者/评估器 LLM provider key(映射到 `HB_API_KEY`);设置此项即选择本地模式。 | — |
| `api-key | 平台 | Humanbound 项目 API key(映射到 `HUMANBOUND_API_KEY`);设置此项即选择平台模式。 | — |
| `endpoint` | 两者皆有 | Agent 集成配置 — 内联 JSON、文件路径或在步骤中构建。本地模式下必填;在平台模式下为可选覆盖项。 | — |
| `provider` | 本地 | 攻击者/评估器 LLM provider(`openai`、`anthropic`、`ollama` 等)。 | `openai` |
| `model` | 本地 | 攻击者/评估器模型(例如 `gpt-4.1`)。除 `ollama` 外的每个 provider 均需提供。 | — |
| `provider-endpoint` | 本地 | 自定义 provider endpoint(例如自托管的 Ollama URL)。 | — |
| `level` | 两者皆有 | 测试深度:`quick` / `unit` / `system` / `acceptance`。 | `quick` |
| `category` | 两者皆有 | 测试引擎:`humanbound/adversarial/owasp_agentic`、`…/owasp_single_turn` 或 `humanbound/behavioral/qa`。 | OWASP agentic |
| `fail-on` | 两者皆有 | 在此严重性或更高等级时使 job 失败:`critical`/`high`/`medium`/`low`/`any`。留空 = 仅报告。 | `high` |
| `scope` | 本地 | scope 文件的路径(允许/受限的 intent)。仅限文件 — 不接受内联内容。 | — |
| `system-prompt` | 本地 | Agent 的系统 prompt 路径,用于提取 scope。 | — |
| `repo` | 本地 | 用于 scope 发现的扫描 repo 路径(`.` = 已 checkout 的工作区)。 | — |
| `context` | 两者皆有 | 额外的评估器上下文 — 字符串或 `.txt` 文件的路径。 | — |
| `version` | 两者皆有 | 要安装的 Humanbound CLI 版本。设为 `""` 获取最新版本。 | `2.6.0` |
| `results-file` | 两者皆有 | 写入 JSON 结果导出文件的路径。 | `humanbound-results.json` |
| `sarif-file` | 两者皆有 | 写入 SARIF 文件的路径。留空则禁用 SARIF。 | `humanbound.sarif` |
# 输出项
| Output | 描述 |
| -------------- | ---------------------------------------------------------------- |
| `mode` | 运行的是哪种模式:`local` 或 `platform` |
| `results-file` | JSON 结果文件的路径(用于 `actions/upload-artifact`) |
| `sarif-file` | SARIF 文件的路径(用于 `github/codeql-action/upload-sarif`) |
# 时间与成本
攻击者/评估器调用会消耗 LLM token(在本地模式下使用您的 key;在平台模式下使用平台的 provider)。级别:`quick`(目前等同于 `unit`,约 20 分钟)、`system` 约 45 分钟、`acceptance` 约 90 分钟 — 请在夜间运行深度级别,而不是在每个 PR 上运行。
# 贡献
欢迎贡献 — 请参阅 [CONTRIBUTING.md](CONTRIBUTING.md)(需要 DCO 签名)。`hb test` 本身的 bug 请提交至 [CLI 仓库](https://github.com/humanbound/humanbound/issues);action 的连接问题请提交[这里](https://github.com/humanbound/actions/issues)。安全报告:[SECURITY.md](SECURITY.md),请勿通过公开 issue 提交。发布历史:[CHANGELOG](CHANGELOG.md)。
# 许可证
本项目中的脚本和文档基于 [Apache-2.0](LICENSE) 协议发布。