For the complete documentation index, see llms.txt. This page is also available as Markdown.

12.5 实战:MiniHarness 安全层集成

本节为 MiniHarness 集成可运行的教学安全层。核心设计是“分层防护:权限 → 护栏 → 批准 → 执行”。

完整代码见 lab/mini_harness/security/,本节聚焦四层防护的设计与集成。

12.5.1 第一层:权限决策(权限模型映射表)

MiniHarness 采用 4 级简化权限模型,下表展示其与 12.2 的 6 级梯度的映射关系:

MiniHarness 4 级
12.2 六级模型
语义
适用场景

DENY

DENY

永不允许

禁止操作(rm -rf /)

ASK

APPROVE_ALWAYS + ASK_FIRST

每次/首次询问

敏感操作需人工确认

AUTO

AUTO_WITH_NOTIFICATION + FULL_TRUST

已批准后自动执行

低风险日常操作

OVERRIDE

OVERRIDE

管理员强制执行

紧急故障恢复(仅管理员)

重要声明:生产系统应采用 12.2 的 6 级梯度以实现精细化权限控制;此处 4 级为 MiniHarness 教学框架的简化版本,便于初学者理解权限决策的核心逻辑。

权限引擎根据四个权限等级做决策。设计简化为权限策略 + 审计日志:

class PermissionLevel(Enum):
    DENY = 0       # 永不允许
    ASK = 1        # 每次询问用户
    AUTO = 2       # 已批准后自动放行(可缓存之前的批准)
    OVERRIDE = 3   # 管理员覆盖

class PermissionDecisionEngine:
    DEFAULT_APPROVAL_SCOPE = "__tool__"

    def register_policy(self, tool_name: str, level: PermissionLevel):
        """为工具注册权限策略"""
        self.policies[tool_name] = level

    async def decide(
        self,
        tool_name: str,
        user_id: str,
        approval_scope: str | None = None,
    ) -> Decision:
        """返回 ALLOW / DENY / ASK_USER"""
        level = self.policies.get(tool_name, PermissionLevel.ASK)

        if level == PermissionLevel.DENY:
            return Decision.DENY

        elif level == PermissionLevel.AUTO:
            # 检查用户曾否批准过
            if self._was_approved_before(user_id, tool_name, approval_scope):
                return Decision.ALLOW
            else:
                return Decision.ASK_USER

        elif level == PermissionLevel.ASK:
            return Decision.ASK_USER

        else:  # OVERRIDE
            return Decision.ALLOW

    def _approval_key(self, user_id: str, tool_name: str, approval_scope: str | None):
        scope = approval_scope or self.DEFAULT_APPROVAL_SCOPE
        return (user_id, tool_name, scope)

    def _was_approved_before(
        self,
        user_id: str,
        tool_name: str,
        approval_scope: str | None = None,
    ) -> bool:
        return self._approval_key(user_id, tool_name, approval_scope) in self.user_approvals

    def record_approval(
        self,
        user_id: str,
        tool_name: str,
        approval_scope: str | None = None,
    ):
        self.user_approvals.add(self._approval_key(user_id, tool_name, approval_scope))

核心设计:策略驱动 + 参数级用户批准缓存,避免对同一低风险调用重复询问,同时避免不同参数复用旧批准。审计日志记录所有决策。

完整实现参见 lab/mini_harness/security/permissions.py

12.5.2 第二层:路径校验

Agent 对用户提供的文件路径必须防御路径穿越攻击。五层递进式防护:

关键点:

  • 不信任用户输入:URL 编码、Unicode、符号链接都可能被攻击者利用

  • 白名单优于黑名单:只允许特定目录(如 /tmp/agent/data),而非禁止特定目录

  • 冗余检查:即使一层被绕过,其他层仍可防护

完整实现参见 lab/mini_harness/security/path_validator.py

12.5.3 第三层:命令护栏

对 bash 等命令执行工具,必须检测并阻止危险命令:

设计策略:

  • 静态黑名单:rm、dd、reboot 等永不允许

  • 管道检测cat file | rm -f / 中的 rm 仍被检测

  • Shell 控制符检测&&;$()、反引号等会被保守阻止,避免危险命令藏在第二段命令中

  • 解释器包装检测:默认阻止 bash -csh -cpython -cnode -e 等内联执行入口,避免黑名单只检查第一层命令而被绕过

  • 子命令白名单:某些包管理器(apt)仅允许 list/search(不允许 remove)

完整实现参见 lab/mini_harness/security/guardrails.py

12.5.4 第四层:安全执行器集成

将权限、护栏、批准三层整合在执行器中:

execute() 的第二个参数是实际副作用函数。权限为 DENY 时,它不会被调用;路径校验会在调用前把参数替换为已验证的绝对路径。HarnessApplication 也使用同一个入口,因此本地工具和 MCP 工具不会形成两条安全强度不同的调用路径。检查点回放同样位于该安全入口之后:每次回放都重新授权,保存的结果绑定原 user_id,不同 principal 不能复用同一会话调用 ID 读取结果。

四层是逐级递进的防线,任何层失败都会阻止执行。当前批准回调是同步函数;如果产品通过网络或 UI 异步征求批准,应在进入执行器前完成交互,或扩展为明确的异步回调接口。

完整实现参见 lab/mini_harness/security/secure_executor.pylab/mini_harness/application.py

12.5.5 部署检查清单

12.5.6 总结

MiniHarness 安全架构的四大防线:权限决策 → 路径校验 → 命令护栏 → 安全执行,形成深度防御。

最后更新于