# 12.5 实战：MiniHarness 安全层集成

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

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

## 权限模型映射表

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 教学框架的简化版本，便于初学者理解权限决策的核心逻辑。

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

```python
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 对用户提供的文件路径必须防御路径穿越攻击。五层递进式防护：

```python
class PathValidator:
    def validate(self, user_path: str) -> str:
        """5层递进式校验"""
        # 第1层：长度检查(防止缓冲区溢出)
        if len(user_path) > 4096:
            raise ValueError("路径过长")

        # 第2层：迭代URL解码(防止多重编码)
        path = self._decode_all_encodings(user_path)

        # 第3层：Unicode规范化(防止Unicode绕过)
        path = unicodedata.normalize('NFC', path)

        # 第4层：路径规范化(移除.. / 冗余 /)
        path = posixpath.normpath(path)

        # 第5层：符号链接解析 + 边界检查
        base = os.path.realpath(self.base_path)
        candidate = os.path.realpath(os.path.join(base, path))
        if os.path.commonpath([base, candidate]) != base:
            raise ValueError("路径穿越")

        return candidate
```

关键点：

* **不信任用户输入**：URL编码、Unicode、符号链接都可能被攻击者利用
* **白名单优于黑名单**：只允许特定目录（如 `/tmp/agent/data`），而非禁止特定目录
* **冗余检查**：即使一层被绕过，其他层仍可防护

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

## 12.5.3 第三层：命令护栏

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

```python
class DangerousCommandDetector:
    DANGEROUS_COMMANDS = {
        "rm", "dd", "mkfs", "reboot", "shutdown", "chmod",
        "sudo", "passwd", "useradd", "cryptsetup"
    }
    SHELL_CONTROL_OPERATORS = ("&&", "||", ";", "\n", "\r", "$(", "`")

    def detect(self, command: str) -> bool:
        """检测是否包含危险命令"""
        tokens = shlex.split(command)
        if any(op in command for op in self.SHELL_CONTROL_OPERATORS):
            return True
        main_cmd = tokens[0].split('/')[-1]  # 移除路径前缀

        # 检查主命令是否在黑名单中
        if main_cmd in self.DANGEROUS_COMMANDS:
            return True

        # 检查管道中的命令(如 ls | rm)
        for piped_cmd in self._extract_piped_commands(command):
            if piped_cmd in self.DANGEROUS_COMMANDS:
                return True

        return False
```

设计策略：

* **静态黑名单**：rm、dd、reboot 等永不允许
* **管道检测**：`cat file | rm -f /` 中的 rm 仍被检测
* **Shell控制符检测**：`&&`、`;`、`$()`、反引号等会被保守阻止，避免危险命令藏在第二段命令中
* **子命令白名单**：某些包管理器（apt）仅允许 list/search（不允许 remove）

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

## 12.5.4 第四层：安全执行器集成

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

```python
class SecureToolExecutor:
    async def execute(self, tool_call: ToolCall, user_id: str):
        """安全执行流程"""
        approval_scope = fingerprint(tool_call.args)  # 例如对排序后的 JSON 参数做 SHA-256

        # 步骤1:权限决策
        decision = await self.permission_engine.decide(
            tool_call.tool_name, user_id, approval_scope=approval_scope
        )
        if decision == Decision.DENY:
            raise PermissionError(f"{tool_call.tool_name} 被拒绝")

        # 步骤2:护栏检查
        if tool_call.tool_name == 'bash_exec':
            if self.guardrail.is_dangerous(tool_call.args['command']):
                raise PermissionError("危险命令被阻止")

        # 步骤3:用户批准(如需)
        if decision == Decision.ASK_USER:
            approved = await self.ask_user(user_id, tool_call)
            if not approved:
                raise PermissionError("用户拒绝")
            self.permission_engine.record_approval(
                user_id, tool_call.tool_name, approval_scope=approval_scope
            )

        # 步骤4:执行
        return await self._do_execute(tool_call)
```

四层是逐级递进的防线，任何层失败都会阻止执行。

完整实现参见 `lab/mini_harness/security/secure_executor.py`。

## 12.5.5 部署检查清单

* [ ] 权限策略已配置（read\_file=AUTO，bash=ASK，delete=DENY）
* [ ] 路径白名单已设置（仅允许 `/tmp/agent/data` 等安全目录）
* [ ] 危险命令黑名单已更新（rm、dd、reboot 等）
* [ ] 审计日志已启用（记录所有权限决策）
* [ ] 用户批准流程已接入（手机通知、邮件等）
* [ ] 测试路径穿越（../、..%2f、..%252f 等编码攻击）
* [ ] 测试权限缓存（同一用户、同一工具、同一参数指纹，第二次才可自动批准）

## 12.5.6 总结

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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://yeasy.gitbook.io/harness_engineering_guide/di-si-bu-fen-an-quan-ping-gu-yu-yan-jin/12_security/12.5_miniharness_security.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
