mcpField
S
signed-audit-trails-recipe

signed-audit-trails-recipe

github.com/wshobson安全41.9k6.3k 次安装2 周前更新
代码仓库

关于 signed-audit-trails-recipe

这是一项讲解如何用 Cedar 策略限制 Claude Code 工具调用并生成签名收据的教程技能,适用于需要审计 Agent 行为的团队。内容涵盖受监管流程及 CI/CD 中的验证方法。

主要功能

  1. 01执行前进行 Cedar 策略检查
  2. 02生成 Ed25519 签名调用收据
  3. 03离线验证收据
  4. 04演示篡改检测
  5. 05提供 CI/CD 验证指南

适用场景

  1. 01记录受监管工作中的策略决策
  2. 02在 CI 中验证自动构建工具调用
  3. 03向协作方提供可验证的 Agent 活动记录

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/wshobson/agents --skill signed-audit-trails-recipe

安装后在 Claude Code 中输入/signed-audit-trails-recipe确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
cedar-policy.md
ci-cd.md
hook-wiring.md
receipt-format.md

详细介绍

Claude Code 工具调用的签名审计追踪

以 Cookbook 风格逐步演示如何为每次 Claude Code 工具调用生成经过加密签名的回执。这是一个教学技能。若要使用运行时实现,请安装 protect-mcp 插件。

它能为你带来什么

每次工具调用(Bash、Edit、Write、WebFetch)都会:

  1. 在执行前根据 Cedar 策略进行评估。如果策略拒绝该调用,工具就不会运行。
  2. 在执行后签名为 Ed25519 回执。回执采用 JCS 规范化,任何人都可以用公钥离线验证。

审计员、监管机构或交易对手之后可以验证每一份回执(步骤 5)。无需网络调用,无需查询供应商,无需信任运营方。

何时使用该模式

  • 受监管环境(金融、医疗、关键基础设施),你需要 Agent 行为不可篡改的证据
  • CI/CD 流水线,你想证明每个自动化构建步骤都通过了策略门禁
  • 多方协作,交易对手希望在不信任你的运营方的情况下验证你的 Agent 行为
  • 合规场景(欧盟 AI 法案第 12 条、Agent 构建软件的 SLSA 来源证明),标准日志记录不足以满足要求

步骤 1:安装钩子配置

使用 /plugin install protect-mcp 安装 protect-mcp 插件。它的钩子会在每次工具调用前运行 evaluate.sh,在调用后运行 sign.sh。两个脚本都从 stdin 读取钩子事件,因为 Claude Code 不设置 TOOL_NAME 或 TOOL_INPUT 变量。钩子配置以及每个脚本向 protect-mcp 传递的内容,请参见 references/hook-wiring.md。

protect-mcp 0.7.4 不会创建签名密钥,而没有密钥时回执就是未签名的。请创建一次 ./protect-mcp.key。该命令永远不会替换已有的密钥:

if [ ! -e ./protect-mcp.key ]; then
  d=$(mktemp -d) && npx [email protected] init --dir "$d" && mv "$d/keys/gateway.json" ./protect-mcp.key
fi

把该文件中的 publicKey 值交给审计员。不要提交该文件,因为它还保存着私钥。

将私钥和回执目录添加到 .gitignore:

echo "/protect-mcp.key" >> .gitignore
echo "/receipts/" >> .gitignore

步骤 2:编写 Cedar 策略

根据 references/cedar-policy.md 中的示例创建 ./protect.cedar。它允许只读工具和一小组 Bash 命令,拒绝 shell 链式调用和破坏性命令,并将写入限制在项目内,且拒绝带 .. 段的路径。

步骤 3:正常使用 Claude Code

启动 Claude Code。每次工具调用都会经过这两个钩子:

You: Please read the README and summarize it.

Claude: I will read README.md.
  [PreToolUse: Read ./README.md -> allow]
  [Tool: Read executes]
  [PostToolUse: receipt rcpt-a8f3c9d2 signed to ./receipts/]

... summary of README ...

一个包含 20 次工具调用的会话会向 ./receipts/receipts.jsonl 追加 20 份回执。

步骤 4:查看回执

protect-mcp 0.7.4 会将每份回执作为一行追加到 ./receipts/receipts.jsonl。打印最新的一条:

tail -n 1 ./receipts/receipts.jsonl | python3 -m json.tool

该回执是一个签名的 v2 信封,其中标明工具名称,且不包含公钥。示例和已签名字段请参见 references/receipt-format.md。

步骤 5:验证回执

将 ./protect-mcp.key 中的 publicKey 值传给验证器:

PUB=$(node -p 'JSON.parse(require("fs").readFileSync("./protect-mcp.key")).publicKey')
npx @veritasacta/[email protected] --replay-chain ./receipts/receipts.jsonl --key "$PUB"

退出码:

代码含义
0每份回执都验证通过
1某份回执验证失败(被篡改、密钥错误或行格式错误)
2无法读取回执文件

步骤 6:演示篡改检测

将最新回执的 decision 从 allow 改为 deny:

python3 -c "
import json
path = './receipts/receipts.jsonl'
lines = open(path).read().splitlines()
r = json.loads(lines[-1])
r['payload']['decision'] = 'deny'
lines[-1] = json.dumps(r)
open(path, 'w').write('\n'.join(lines) + '\n')
"

npx @veritasacta/[email protected] --replay-chain ./receipts/receipts.jsonl --key "$PUB"

验证器会以退出码 1 退出,并报告哪一行验证失败。Ed25519 签名不再与被篡改载荷的 JCS 规范化字节匹配。

恢复该字段后,验证会再次通过。

加密机制的工作原理

两个不变量确保收据可在离线状态下由任何符合规范的实现验证:

  1. 签名前执行 JCS 规范化(RFC 8785)。按 UTF-16 代码单元排序键、尽可能减少空白、不规范化字符串。对于相同的收据内容,两个独立实现会生成字节完全相同的签名载荷。
  2. 对规范化后的字节执行 Ed25519 签名(RFC 8032)。 确定性、固定大小、不依赖随机数。

protect-mcp 0.7.4 收据不包含指向上一条收据的链接,因此无法检测收据是否被删除。

正式的线路格式请参阅 draft-farley-acta-signed-receipts。

跨实现互操作

目前,收据格式有四种独立实现:

实现语言用途
protect-mcpTypeScriptClaude Code、Cursor、MCP 主机
protect-mcp-adkPythonGoogle Agent Development Kit
sb-runtimeRust操作系统级沙箱(Landlock + seccomp)
APS governance hookPythonCrewAI、LangChain

由其中任何一种实现生成的收据,都可以通过 @veritasacta/verify 验证。 审计员无需信任操作者选择的工具:格式本身就是约定。

CI/CD 集成

在 CI 中验证收据,以便被篡改的收据能导致构建失败。 references/ci-cd.md 提供了一个 GitHub Actions 工作流,会在向默认分支推送时运行。它从仅限分支的环境中安装签名密钥、运行 Agent、验证收据并上传收据。它不会在拉取请求上运行,因为那会将密钥交给未经审核的代码。

与 Agent 构建软件的 SLSA 来源证明组合使用

当 Claude Code 构建并发布软件时(将 npm install、 npm build、npm publish 作为工具调用运行),收据链就是逐步构建日志。SLSA Provenance v1 为此提供了扩展点:byproducts 字段可以在构建证明旁引用收据链。

agent-commit build type 使用 ResourceDescriptor 结构说明了这一模式:

{
  "name": "decision-receipts",
  "digest": { "sha256": "..." },
  "uri": "oci://registry/org/build-xyz/receipts:sha256-...",
  "annotations": {
    "predicateType": "https://veritasacta.com/attestation/decision-receipt/v0.1",
    "signerRole": "supervisor-hook"
  }
}

SLSA 来源证明由构建器身份签名;收据证明由 supervisor-hook 身份签名。两个信任域通过副产物层交叉引用。有关组合方式的讨论,请参阅 slsa-framework/slsa#1594。

常见问题

私钥被提交到版本控制中。 生成的 ./protect-mcp.key 不得提交。上述示例会将其添加到 .gitignore 中。如果不慎提交了密钥,请立即轮换。将密钥和 ./receipts/receipts.jsonl 移至存档,然后再次运行步骤 1 中的命令。 使用旧公钥验证存档的收据。

通过 stdin 传递钩子载荷。 Claude Code 不会设置 $TOOL_NAME 或 $TOOL_INPUT 变量。钩子命令如果传入 --tool "$TOOL_NAME",会发送空工具名称,因此策略会拒绝每次调用。应像插件脚本那样从 stdin 读取载荷。

CI 中的收据目录。 如果 Claude Code 在 CI 中运行,请在作业结束时将收据作为构件上传,否则作业结束时收据就会丢失。

缺少策略。 如果 ./protect.cedar 不存在,evaluate.sh 会向 stderr 打印警告并允许调用。直到你在步骤 2 中创建策略之前,都不会对任何调用进行限制。

此 Marketplace 中的相关项目

  • protect-mcp — 运行时钩子实现 (在生产环境中使用此插件)
  • review-agent-governance — 在执行审查界面操作前要求人工批准;可与 protect-mcp 组合使用

参考

评论

支持 Markdown