DeerFlow 2.0 · 从入门到精通 目录

§12 护栏与权限沙箱

DeerFlow 在工具调用真正发生前,会过一道护栏。这是它敢默认放开工具调用的原因。

GuardrailMiddleware + GuardrailProvider

架构是「中间件 + 可插拔 provider」:

GuardrailRequest 携带的字段(2.0 已补全运行时归因):

@dataclass
class GuardrailRequest:
    tool_name: str
    tool_input: dict
    agent_id: str | None = None
    thread_id: str | None = None
    is_subagent: bool = False
    timestamp: str = ""
    user_id: str | None = None        # DeerFlow 内部稳定用户 ID
    user_role: str | None = None      # admin / user
    oauth_provider: str | None = None # 未来 OAuth/SSO
    oauth_id: str | None = None
    run_id: str | None = None         # run 级审计
    tool_call_id: str | None = None   # 单次调用定位

GuardrailDecision 表达 allow / deny、原因、policy_id、元数据。

身份只信服务端

关键安全点:Gateway 注入只信任服务端认证态 request.state.user。客户端 body 里伪造的 user_id / user_role / oauth_* 不会覆盖服务端身份。这堵死了「假装是 admin」的越权路。

第二道护栏:ReadBeforeWriteMiddleware

代码写入还有一道新鲜度护栏。规则很硬:

  1. read_file 成功 → 记一个 read-mark:sha256(当前完整文件内容)
  2. 改已存在文件(write_file 覆盖 / append / str_replace)前,校验「最新 read-mark 的 hash == 当前文件 hash」。
  3. 不匹配 → 拦截,不执行写入,返回「请先读该文件」。
  4. 写入成功会立刻让上一次 read-mark 过期 → 连续改之间被逼着重读。
  5. 写不存在的新文件 → 放行。

默认开启,挂在中间件链尾、SandboxAudit 之后。对并行同文件写入,用 per-path 锁保证确定性拦截。

标叔的结论:DeerFlow 的安全是「双层 + 默认开」。护栏管「能不能调」,读写门管「改文件前看没看」。你做自己的 provider,至少把 user_role 用起来——比如 admin:bash 才放行危险工具。

能力讲完,来到界面与流式。下一章讲终端工作台。