@@ -61,10 +61,12 @@ tRPC-Agent 的 Tool、MCP Tool、Skill 和 CodeExecutor 能让 Agent 执行脚
6161| --- | --- | --- |
6262| 安全检查器代码 | 已完成 | ` trpc_agent_sdk/tools/safety/ ` |
6363| CLI 工具 | 已完成 | ` scripts/tool_safety_check.py ` |
64+ | Manifest 验收工具 | 已完成 | ` scripts/tool_safety_manifest_report.py ` |
6465| 策略示例 | 已完成 | ` examples/tool_safety/tool_safety_policy.yaml ` |
65- | 31 条公开样例 | 已完成 | ` examples/tool_safety/samples/ ` |
66+ | 40 条公开样例 | 已完成 | ` examples/tool_safety/samples/ ` |
67+ | 样例 manifest | 已完成 | ` examples/tool_safety/samples/manifest.yaml ` |
6668| 报告示例 | 已完成 | ` examples/tool_safety/tool_safety_report.json ` |
67- | 31 条样例汇总报告 | 已完成 | ` examples/tool_safety/all_reports.json ` |
69+ | 40 条样例汇总报告 | 已完成 | ` examples/tool_safety/all_reports.json ` |
6870| 审计日志示例 | 已完成 | ` examples/tool_safety/tool_safety_audit.jsonl ` |
6971| 自动化测试 | 已完成 | ` tests/tools/safety/ ` |
7072| 设计说明 | 已完成 | 本文档 |
@@ -109,6 +111,7 @@ Tool / Skill / MCP Tool / CodeExecutor
109111| ` _wrapper.py ` | 独立 wrapper,执行前扫描、审计、埋点和拦截 |
110112| ` _filter.py ` | tRPC-Agent Filter 接入示例 |
111113| ` scripts/tool_safety_check.py ` | 命令行扫描工具 |
114+ | ` scripts/tool_safety_manifest_report.py ` | Manifest 驱动验收和 deterministic 报告生成工具 |
112115
113116## 规则体系
114117
@@ -118,14 +121,16 @@ Tool / Skill / MCP Tool / CodeExecutor
118121| --- | --- |
119122| ` allow ` | 当前静态策略未命中风险,允许执行 |
120123| ` deny ` | 命中高危或严重风险,执行前拒绝 |
121- | ` needs_human_review ` | 命中不确定或中等风险,需要人工复核 |
124+ | ` needs_human_review ` | 命中不确定或中等风险,需要人工复核,默认记录但不阻断 |
122125
123126最终决策由命中的 finding 聚合得到:
124127
125128- 任意 finding 为 ` deny ` ,最终结果为 ` deny ` 。
126129- 没有 ` deny ` ,但存在 ` needs_human_review ` ,最终结果为 ` needs_human_review ` 。
127130- 没有 finding 时,最终结果为 ` allow ` 。
128131
132+ 扫描决策和执行拦截分开处理:` deny ` 默认会在执行前拦截;` needs_human_review ` 默认只写入报告、审计和 telemetry,不阻断执行;设置 ` block_on_review=True ` 后,` needs_human_review ` 也会阻断。
133+
129134### 风险等级
130135
131136| 风险等级 | 典型含义 |
@@ -326,7 +331,7 @@ if report.blocked:
326331
327332# ## Wrapper 接入
328333
329- ` ToolSafetyGuard` 适合不直接修改核心执行链路时使用。它会在真实执行函数之前扫描脚本,写审计日志,设置 OpenTelemetry attributes,并在非 `allow` 时阻止执行 。
334+ ` ToolSafetyGuard` 适合不直接修改核心执行链路时使用。它会在真实执行函数之前扫描脚本,写审计日志,设置 OpenTelemetry attributes,并按 `deny` 或 `block_on_review=True` 策略阻止执行 。
330335
331336` ` ` python
332337from trpc_agent_sdk.tools.safety import ToolSafetyGuard
@@ -358,6 +363,15 @@ if result.blocked:
358363 # Return or log the structured report instead of executing the tool.
359364` ` `
360365
366+ 如果希望人工复核决策也阻断执行:
367+
368+ ` ` ` python
369+ guard = ToolSafetyGuard(
370+ audit_log_path="tool_safety_audit.jsonl",
371+ block_on_review=True,
372+ )
373+ ` ` `
374+
361375如果希望直接抛错,可使用:
362376
363377` ` ` python
@@ -476,8 +490,10 @@ if not result.is_continue:
476490
477491当前测试覆盖:
478492
479- - 31 条公开样例,其中包含 issue 指定的 12 类必测场景和额外边界场景。
493+ - 40 条公开样例,其中包含 issue 指定的 12 类必测场景和额外边界场景。
494+ - Manifest 驱动验收,校验 expected decision 和 required rule ids。
480495- YAML policy 加载和匹配。
496+ - Strict policy validation,拒绝未知字段、错误类型和负数限制。
481497- 结构化报告字段。
482498- 500 行脚本扫描性能。
483499- 命令行参数、工作目录、超时和输出大小检查。
@@ -486,15 +502,30 @@ if not result.is_continue:
486502- Filter 执行前拦截和审计日志。
487503- CLI 输出和返回码。
488504
489- # ## 扫描 31 个公开样例
505+ # ## 扫描 40 个公开样例
490506
491- 仓库中已提供一份汇总报告 :
507+ 仓库中已提供一份 deterministic 汇总报告 :
492508
493509` ` ` text
494510examples/tool_safety/all_reports.json
495511` ` `
496512
497- 也可以重新扫描生成:
513+ 推荐使用 manifest 验收脚本重新生成:
514+
515+ ` ` ` bash
516+ .venv/bin/python scripts/tool_safety_manifest_report.py \
517+ --strict-policy \
518+ --output examples/tool_safety/all_reports.json
519+ ` ` `
520+
521+ 该命令会校验:
522+
523+ - 40/40 expected decision 匹配。
524+ - 40/40 required rule ids 匹配。
525+ - 读取密钥、危险删除、非白名单网络外连三类样例均不会被 allow。
526+ - 安全样例不会被 deny。
527+
528+ 也可以使用通用 CLI 扫描目录:
498529
499530` ` ` bash
500531.venv/bin/python scripts/tool_safety_check.py \
@@ -503,41 +534,19 @@ examples/tool_safety/all_reports.json
503534 --output examples/tool_safety/all_reports.json
504535` ` `
505536
506- 样例覆盖:
537+ 样例期望决策和 required rule ids 由 `examples/tool_safety/samples/manifest.yaml` 维护。
507538
508- | 样例 | 期望决策 |
509- | --- | --- |
510- | `aiohttp_non_whitelist.py` | `deny` |
511- | `apt_install.sh` | `deny` |
512- | `background_process.sh` | `needs_human_review` |
513- | `bash_pipe.sh` | `deny` |
514- | `command_substitution.sh` | `needs_human_review` |
515- | `credential_file_key.py` | `deny` |
516- | `danger_delete.sh` | `deny` |
517- | `dependency_install.sh` | `deny` |
518- | `fork_bomb.sh` | `deny` |
519- | `human_review.py` | `needs_human_review` |
520- | `infinite_loop.py` | `needs_human_review` |
521- | `long_sleep.sh` | `needs_human_review` |
522- | `network_non_whitelist.py` | `deny` |
523- | `network_whitelist.py` | `allow` |
524- | `npm_install.sh` | `deny` |
525- | `os_system.py` | `needs_human_review` |
526- | `pip_module_install.py` | `deny` |
527- | `private_key_literal.py` | `deny` |
528- | `privilege_escalation.sh` | `deny` |
529- | `read_env.py` | `deny` |
530- | `read_secret.py` | `deny` |
531- | `safe_bash.sh` | `allow` |
532- | `safe_file_read.py` | `allow` |
533- | `safe_python.py` | `allow` |
534- | `sensitive_output.py` | `deny` |
535- | `shell_injection.py` | `needs_human_review` |
536- | `socket_access.py` | `needs_human_review` |
537- | `subprocess_call.py` | `needs_human_review` |
538- | `subprocess_danger_delete.py` | `deny` |
539- | `system_overwrite.sh` | `deny` |
540- | `unknown_network_dynamic.py` | `needs_human_review` |
539+ 新增高价值绕过样例包括:
540+
541+ - ` base64 | sh`
542+ - ` python -c`
543+ - ` bash -c` / `sh -c`
544+ - 动态 URL
545+ - 动态 `.env` / `~/.ssh` 路径
546+ - ` curl --data-binary @.env`
547+ - ` find -delete`
548+ - ` xargs rm -rf`
549+ - ` os.getenv("API_TOKEN")` 外传
541550
542551# ## 性能验证
543552
@@ -658,7 +667,8 @@ trpc_agent_sdk/tools/safety/
658667└── _wrapper.py
659668
660669scripts/
661- └── tool_safety_check.py
670+ ├── tool_safety_check.py
671+ └── tool_safety_manifest_report.py
662672
663673examples/tool_safety/
664674├── README.md
@@ -670,22 +680,31 @@ examples/tool_safety/
670680 ├── aiohttp_non_whitelist.py
671681 ├── apt_install.sh
672682 ├── background_process.sh
683+ ├── base64_exec_review.sh
684+ ├── bash_inline_command.sh
673685 ├── bash_pipe.sh
674686 ├── command_substitution.sh
675687 ├── credential_file_key.py
688+ ├── curl_env_upload.sh
676689 ├── danger_delete.sh
677690 ├── dependency_install.sh
691+ ├── dynamic_secret_path.py
692+ ├── dynamic_url_join.py
693+ ├── find_delete_review.sh
678694 ├── fork_bomb.sh
679695 ├── human_review.py
680696 ├── infinite_loop.py
681697 ├── long_sleep.sh
698+ ├── manifest.yaml
682699 ├── network_non_whitelist.py
683700 ├── network_whitelist.py
684701 ├── npm_install.sh
702+ ├── os_getenv_token_exfiltration.py
685703 ├── os_system.py
686704 ├── pip_module_install.py
687705 ├── private_key_literal.py
688706 ├── privilege_escalation.sh
707+ ├── python_inline_command.sh
689708 ├── read_env.py
690709 ├── read_secret.py
691710 ├── safe_bash.sh
@@ -697,7 +716,8 @@ examples/tool_safety/
697716 ├── subprocess_call.py
698717 ├── subprocess_danger_delete.py
699718 ├── system_overwrite.sh
700- └── unknown_network_dynamic.py
719+ ├── unknown_network_dynamic.py
720+ └── xargs_rm_review.sh
701721
702722tests/tools/safety/
703723├── test_audit.py
0 commit comments