humanbound/actions

GitHub: humanbound/actions

Humanbound Actions 将 Humanbound CLI 封装为 GitHub Action,让团队在 CI 流程中对 AI Agent 自动进行对抗性安全测试并作为质量门禁。

Stars: 3 | Forks: 0

Humanbound

Humanbound Actions

每次 push 时对 AI agent 进行对抗性安全测试。
hb test 封装为 GitHub Action: 符合 OWASP 标准的对抗性与行为测试 — prompt injection、工具滥用、数据泄露等 —
测试结果将作为构建的门禁,并显示在 GitHub 的 Security 标签页中。

快速开始 · 工作原理 · 场景 · 输入项 · 文档

License Docs Discord

- **符合 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) 协议发布。
标签:请求拦截