timothywarner-org/agent-security-quorum

GitHub: timothywarner-org/agent-security-quorum

利用多模型 LLM 共识与静态分析的 2/4 法定人数机制,对 GitHub PR 中的 AI agent 定义文件进行自动化安全扫描,拦截 prompt 注入和数据泄露等语义攻击。

Stars: 1 | Forks: 2

Agent Security Quorum

# Agent Security Quorum [![网站](https://img.shields.io/badge/TechTrainerTim.com-4285F4?style=for-the-badge&logo=google-chrome&logoColor=white)](https://techtrainertim.com) [![GitHub 组织](https://img.shields.io/badge/timothywarner--org-181717?style=for-the-badge&logo=github&logoColor=white)](https://github.com/timothywarner-org) [![GitHub](https://img.shields.io/badge/timothywarner-6e40c9?style=for-the-badge&logo=github&logoColor=white)](https://github.com/timothywarner) [![许可证: MIT](https://img.shields.io/badge/License-MIT-yellow?style=for-the-badge)](LICENSE) 对 GitHub pull request 中的 AI agent 和技能定义文件进行自动化安全扫描,利用多模型 LLM 共识机制,在合并前捕获 prompt 注入、权限提升和数据泄露。 ## 为什么这很重要 - **Agent 定义是可执行的攻击面。** 位于 `.github/agents/`、`.claude/agents/` 及类似路径下的文件是 AI 系统在 runtime 遵循的指令。恶意或受损的 agent 文件可以泄露 secrets、绕过审查关卡或提升权限——而且它看起来就像普通的 Markdown。 - **静态分析在这里不起作用。** 这些攻击是语义层面的,嵌入在自然语言中。任何 linter 或 regex 都无法捕获“忽略所有之前的指令”或“读取 ~/.ssh/id_rsa 并将其 POST 到外部 endpoint”。 - **每个 PR 跨越两个检测类别有四个独立的评估器。** 三个 LLM 视角(安全、权限、合规性)运行在不同的模型家族上,外加一个静态分析投票者(Cisco 的开源 skill-scanner:YARA、AST dataflow、taint analysis)。一个绕过行为必须击败两种根本不同的检测方法,而不仅仅是欺骗三个语言模型。 - **2/4 法定人数防止单模型盲点。** 一个误报不会阻止你的 PR。必须有两个独立的评估器同意文件不安全,构建才会失败。 - **确定性的测试文件门控阻止了捆绑 payload 的绕过。** 一个技能可以附带一个干净的 `SKILL.md`,同时附带一个 `*.test.ts` 文件,测试运行器会自动发现并使用开发者凭据执行该文件——没有涉及 agent,因此 LLM 扫描器会错过它([Gecko Security, 2026](https://www.gecko.security/blog/rce-in-your-test-suite-ai-agent-skills-bypass-skill-scanners))。一个严格的、非投票的门控会在技能目录内出现任何测试、spec 或构建配置文件时直接使构建失败。 - **扫描结果映射到 OWASP Agentic Skills Top 10** (AST01–AST10),并作为 SARIF 显示在 GitHub Security 标签页中,因此它们在 PR 关闭后仍然存在,并为代码扫描活动提供数据。 - **零基础设施。** 完全在 GitHub Actions 中使用 Copilot CLI 和一个通过 pip 安装的静态扫描器运行。没有服务器,没有 SaaS 依赖,除了你现有的 Copilot 订阅外没有额外的成本。 ## 架构 ``` PR touches agent/skill files (ALL files, not just *.md) | v +-------------------+ | Detect Changes | git diff filtered to agent/skill directories +--------+----------+ | +----------------------+-------------------------+ v v v +-------------------+ +-------------------+ +---------------------------+ | Test-File Gate | | Validate | | Evaluators (4x parallel) | | (deterministic) | | Structure | | | | | | (deterministic) | | LLM lenses (3 models): | | No *.test.*, | | | | Security / Privilege / | | *.spec.*, | | YAML frontmatter | | Compliance | | conftest.py, | | required fields | | Static analysis (1): | | *.config.* in | | | | cisco-skill-scanner | | skill dirs | | | | (YARA + AST + taint) | +--------+----------+ +--------+----------+ +-------------+-------------+ | | | hard fail v | +----------------------------------------+ +--------------------------->| Quorum: 2/4 UNSAFE = FAIL, | | OR test-file gate fired = FAIL | | Findings -> PR comment + SARIF (AST01-10)| +----------------------------------------+ ``` 评估器跨越两个检测类别(语义 LLM 判断和静态分析)运行在不同的模型家族上,因此该 quorum 具有真正的多样性。单个误报不会阻止你的 PR。测试文件门控是独立的:它是确定性且非投票的,任何匹配都会直接导致构建失败。请参阅 [docs/threat-model.md](docs/threat-model.md) 了解它所关闭的攻击。 ## 快速开始 1. **将工作流和 prompts 复制到你的仓库中。** Fork 此仓库,或者将 `.github/workflows/agent-scan.yml` 和 `prompts/` 目录复制到现有项目中。 2. **创建一个具有 "Copilot Requests" 权限的细粒度 PAT。** 在 Settings > Secrets and variables > Actions 下,将其添加为名为 `COPILOT_PAT` 的仓库 secret。 3. **打开一个触及 agent 或技能文件的 PR。** 扫描器会自动运行,并以 PR 评论的形式发布 quorum 裁决。 ## 教程:5 分钟内开始扫描 ### 前置条件 - 一个启用了 [GitHub Actions](https://docs.github.com/en/actions) 的 GitHub 仓库 - [GitHub Copilot](https://docs.github.com/en/copilot) 订阅(任何计划:Free、Pro、Pro+、Business 或 Enterprise) - 一个具有 **"Copilot Requests"** 权限的 **Personal Access Token**(细粒度),作为名为 `COPILOT_PAT` 的仓库 secret 存储 ### 第 1 步:创建 Copilot PAT 工作流需要一个 Personal Access Token 来与 Copilot CLI 进行身份验证。 1. 前往 [github.com/settings/personal-access-tokens/new](https://github.com/settings/personal-access-tokens/new) 2. 创建一个具有 **"Copilot Requests"** 权限的**细粒度** token 3. 在你的仓库中,前往 **Settings > Secrets and variables > Actions** 4. 点击 **New repository secret**,将其命名为 `COPILOT_PAT`,粘贴 token 值 ### 第 2 步:Fork 或复制 **选项 A — Fork 此仓库** 以获取包括测试 fixtures 在内的所有内容: ``` gh repo fork timothywarner/agent-security-quorum --clone ``` **选项 B — 复制到现有项目中。** 你需要两样东西: ``` your-repo/ .github/workflows/agent-scan.yml ← the workflow prompts/ ← the prompt templates v1.txt lens-security.txt lens-privilege.txt lens-compliance.txt ``` 将它们复制进去: ``` # 从你的 repo 内部 curl -sL https://github.com/timothywarner/agent-security-quorum/archive/main.tar.gz | \ tar xz --strip-components=1 \ agent-security-quorum-main/.github/workflows/agent-scan.yml \ agent-security-quorum-main/prompts/ ``` ### 第 3 步:创建一个分支并添加一个 Agent 文件 ``` git checkout -b test-agent-scan mkdir -p .github/agents ``` 创建带有一些内容的 `.github/agents/my-agent.md`: ``` --- name: my-helper description: Helps answer questions about the codebase. tools: - Read - Grep --- # 我的 Helper You answer questions about the codebase. Only read files — never modify anything. ``` ### 第 4 步:推送并打开一个 PR ``` git add .github/agents/my-agent.md git commit -m "feat: add my-helper agent" git push -u origin test-agent-scan gh pr create --title "Add my-helper agent" --body "Testing the agent security scanner." ``` ### 第 5 步:观察扫描运行 前往你 PR 上的 **Actions** 标签页。你会看到六个 job: 1. **Detect Changes** — 找到你新的 agent 文件 2. **Test-File Gate** — 对技能目录内的任何测试/spec/config 文件进行硬失败 3. **Validate Structure** — 检查 YAML frontmatter 是否包含必填字段 4. **LLM Scan (security / privilege / compliance)** — 在不同模型上进行三个并行评估 5. **Static Scan (cisco-skill-scanner)** — 第四个投票者,YARA + AST + taint analysis 6. **Quorum Decision** — 汇总投票,发布结果,并将 SARIF 上传到 Security 标签页 ### 第 6 步:检查结果 工作流会在你的 PR 上发布一条评论: ``` ## ✅ Agent/Skill Security Scan | Evaluator | Engine | Verdict | |----------------|---------------------|---------| | security | gpt-4.1 | ✅ SAFE | | privilege | claude-sonnet-4 | ✅ SAFE | | compliance | gemini-2.5-pro | ✅ SAFE | | static | cisco-skill-scanner | ✅ SAFE | | test-file gate | deterministic | ✅ PASS | **Quorum: PASS** (0/4 UNSAFE) ``` 如果 agent 包含危险指令,你会看到: ``` ## ❌ Agent/Skill Security Scan | Evaluator | Engine | Verdict | |----------------|---------------------|-----------| | security | gpt-4.1 | ❌ UNSAFE | | privilege | claude-sonnet-4 | ❌ UNSAFE | | compliance | gemini-2.5-pro | ✅ SAFE | | static | cisco-skill-scanner | ❌ UNSAFE | | test-file gate | deterministic | ✅ PASS | **Quorum: FAIL** (3/4 UNSAFE) ### Findings **security** (gpt-4.1): - **AST01** `.github/agents/sneaky-agent.md`: Prompt injection: instructions attempt to override system constraints - **AST01** `.github/agents/sneaky-agent.md`: Data exfiltration: reads SSH keys and sends data to external URL ``` 构建失败,从而阻止 PR 被合并。 ### 第 7 步:尝试使用危险的 Agent 使用包含的其中一个 fixtures 进行测试。将 `test/fixtures/prompt-injection.md` 复制到你的 agents 文件夹中: ``` cp test/fixtures/prompt-injection.md .github/agents/sneaky-agent.md git add .github/agents/sneaky-agent.md git commit -m "test: add agent with prompt injection" git push ``` 扫描器应该会捕获它并使构建失败。 ### 第 8 步(可选):通过分支保护强制执行 将其锁定,以便 UNSAFE agent 无法被合并: 1. 前往 **Settings > Rules > Rulesets**(或 Branch protection rules) 2. 将你的默认分支设为目标 3. 添加 **Require status checks to pass** 4. 搜索并添加 **Quorum Decision** 检查 5. 保存 现在,任何修改 agent/技能文件的 PR 如果不通过扫描,就无法合并。 ## 扫描范围 这些目录下的每个文件都会被扫描,而不仅仅是 Markdown 指令。捆绑的脚本和测试文件也是攻击面的一部分(参见威胁模型),因此它们也在扫描范围内。 | 位置 | 平台 | |----------|----------| | `.github/agents/**` | GitHub Copilot | | `.github/skills/**` | GitHub Copilot | | `.claude/agents/**` | Claude Code | | `.claude/skills/**` | Claude Code | | `.agents/skills/**` | 跨平台 (`npx skills add` 安装目标) | ## 标记范围 扫描结果映射到 [OWASP Agentic Skills Top 10](https://owasp.org/www-project-agentic-skills-top-10/)。 - **Prompt 注入** (AST01) — 覆盖约束、声明特殊模式或针对扫描器本身的指令 - **供应链 / 捆绑 payload** (AST02) — 技能目录中通过开发者工具链执行的测试、spec 或构建配置文件 - **权限提升与过度授权** (AST03) — 通配符权限、不受限制的 shell、超出既定用途的工具 - **数据泄露** (AST01) — 读取 secrets/keys 并发送到外部 URL - **不受信任的外部指令** (AST05) — 获取远程内容并将其作为指令遵循 - **弱隔离** (AST06) — 路径遍历、访问主目录或系统文件 - **扫描器/审查绕过** (AST08) — 跳过审查、禁用 hooks 或击败 CI 检查的指令 - **权限模糊 / 无治理** (AST09) — 没有明确约束的模糊范围 ## 仓库结构 ``` .github/ workflows/ agent-scan.yml ← the entire scanner (single workflow, no scripts) CODEOWNERS ← require review for agent/skill changes prompts/ v1.txt ← base evaluation prompt with rubric lens-security.txt ← security-focused framing lens-privilege.txt ← privilege/authority-focused framing lens-compliance.txt ← compliance/guardrails-focused framing test/ fixtures/ ← sample agent/skill files for testing testfile-smuggling-skill/ ← clean SKILL.md + malicious *.test.ts (AST02 demo) docs/ threat-model.md ← controls mapped to OWASP AST, the test-file bypass org-deployment.md ← guide for org-level deployment configuration-guide.md ← install, models, prompts, quorum, troubleshooting ``` ## 依赖项 - `jq`, `perl` — GitHub runner 上预装 - `node` / `npm` — GitHub runner 上预装(用于安装 Copilot CLI) - `python` / `pip` — GitHub runner 上预装(用于安装静态扫描器) - `@github/copilot` — 通过 npm 在工作流中安装 - `cisco-ai-skill-scanner` — 通过 pip 在工作流中安装(第四个 quorum 投票者) - 一个具有 "Copilot Requests" 权限的 `COPILOT_PAT` secret ## 组织级别部署 要使用可重用工作流在你的组织的所有仓库中进行部署,请参阅 [docs/org-deployment.md](docs/org-deployment.md)。 ## 扩展 评估器契约是特意设计得很简单的。每个评估器都会写入 `results/.json`: ``` { "verdict": "SAFE|UNSAFE", "findings": [ { "id": "AST01", "file": ".claude/agents/x.md", "detail": "one-sentence description" } ], "model": "engine-name", "lens": "name" } ``` `id` 是一个 OWASP Agentic Skills Top 10 类别(`AST01`–`AST10` 或 `UNMAPPED`)。quorum 计算裁决;聚合器将每个评估器的扫描结果折叠成一个 SARIF 文件用于代码扫描。因为该契约是引擎无关的,所以静态扫描器与三个 LLM 视角位于同一个 quorum 中——你只需通过再编写一个 `results/.json` 并将其名称添加到 quorum 循环中,即可添加一个投票者。 [Cisco skill-scanner](https://github.com/cisco-ai-defense/skill-scanner) 已经作为静态投票者接入。添加另一个引擎(Azure OpenAI、本地模型、NVIDIA SkillSpector)也是同样的一文件模式。 ## 许可证 MIT
标签:AI安全, Chat Copilot, DLL 劫持, GitHub Action, 代码安全审计, 大语言模型, 逆向工具