NovaCode 终端:编辑 README.md 前弹出确认,选项是允许、本次模式不再询问、拒绝

终端 AI 编码助手

NovaCode

运行在终端中的 AI 编程助手,通过自然语言读写代码、执行命令,并管理权限与长会话。

  • Python
  • Textual
  • MCP
  • OS Sandbox
04 / 05 · DOCUMENTATION

权限与执行边界

所有入口使用同一个信任档案工厂,审批规则和 OS 沙箱各自解决不同问题。

入口一致,工作目录独立

TUI、Print、Remote、Worker、子 Agent 和 Skill fork 都通过 build_trust_profile 构造信任状态,避免某个入口漏挂路径校验或沙箱。工作树和 Worker 按自己的工作目录重建档案,不能修改父 Agent 共享的 Bash 对象。

权限检查组合危险命令检测、显式规则、路径范围和权限模式。系统沙箱约束实际命令可访问的资源,交互审批决定某次工具调用是否获得允许,两者不能互相替代。

从模型意图到系统能力

层次判断内容作用范围
工具注册与启用该工具是否存在、当前入口是否可用模型可调用的能力集合
前置 Hook项目流程是否允许该次调用执行前的业务与流程规则
权限检查危险命令、显式规则、文件路径与模式此次工具是否允许或需确认
参数校验输入是否符合工具模型避免执行非法或不完整参数
OS 沙箱命令实际能访问哪些资源Bash 执行的操作系统边界

模型提出“修改这个文件”只是请求,不是授权事实。即使提示词要求只读,也需要执行层拒绝写入;即使用户允许某次写入,也不能由此推断后续任意命令都获得了许可。

规则来自用户、项目和本地层,构造档案时明确相应路径。命令类会检查危险命令和显式拒绝或询问规则,文件类会检查目标路径及受保护文件。不同工具应按实际作用检查,而不是仅凭工具名称包含“读取”或“执行”决定。

请求沙箱不等于沙箱已生效

沙箱先创建,再检查 available(),随后执行 prepare(config),准备后还会检查可用性。只有请求开启、后端可用、准备完成且配置允许自动放行时,才设置相应授权标记。

novacode/novacode/permissions/trust_profile.pyL137-154 @8484bf0
def attach_profile_to_bash(
    registry: Any, profile: TrustProfile, *, clone: bool = False
) -> Any:
    """把档案里的 OS 沙箱与 work_dir 挂到注册表的 Bash 工具上。

    clone=True 时浅拷贝 Bash 并注册回 registry(worktree / 队友必须用克隆,
    避免污染父 Agent 共享的 Bash 对象与其 deny 路径,P10)。
    """
    bash = registry.get("Bash")
    if bash is None:
        return None
    if clone:
        bash = copy.copy(bash)
        registry.register(bash)
    bash.sandbox = profile.sandbox
    bash.sandbox_config = profile.sandbox_config
    bash.work_dir = profile.work_dir
    return bash
子目录和 Worker 克隆 Bash 后再挂载档案,避免把子任务的工作目录写回父对象。

请求了沙箱但准备失败时,Bash 会拒绝裸执行,不会静默降级为不受约束的命令。Linux 使用 bwrap,macOS 使用 Seatbelt;能否运行仍取决于本机环境与真实准备结果。

请求与准备结果有效含义
未请求 OS 沙箱仍执行权限规则,但没有该层系统隔离
请求后端不可用或准备失败不开启沙箱自动放行,执行路径应失败关闭
后端准备成功、未启用自动放行沙箱约束与审批规则分别生效
后端准备成功且允许自动放行只有对应有效档案支持相应放行

sandbox_requested、sandbox_available 和 sandbox_enabled 表示不同事实。前两者描述请求与运行环境,最后一个还受自动放行配置影响;界面或日志只显示“配置已开启”容易掩盖准备失败。

路径范围也必须随工作目录重建。若父 Agent 在主工作树、Worker 在另一个 worktree,共享并改写同一个 Bash 实例会让父任务意外使用子任务路径。当前通过克隆 Bash 并挂载独立档案避免这种对象污染。

非交互路径的 ask

没有人能响应的 Print 或后台路径,遇到 ask 默认拒绝。允许某个工具不能等同于自动允许后续所有 Worker、所有路径或所有命令,审批需要保留作用范围。

用户明确选择绕过审批的权限模式,是另一种有效档案状态;它不会凭空创建 OS 隔离。文档和界面应同时能说明权限模式及沙箱是否真正可用。

只读规划与实际执行

Plan Mode 用于先分析和生成方案,写入能力受当前模式约束;退出规划后再恢复执行所需权限。计划批准、工具批准和 OS 沙箱准备是三个不同判断,批准一份计划不能代替执行时的参数和路径检查。

在 Worker 场景中,审批还要同时匹配当前运行和有效审批 ID。计划已经结束、取消或被替换后,旧的允许响应必须失效。这种关联约束保护的是时间上的授权范围,文件路径约束保护的是空间上的范围。

已完成机制与开放边界

当前实现统一了各入口档案和主要授权路径,但不能据此宣称已通过所有平台、所有命令形式的完整安全审计。尤其真实 macOS Seatbelt 需要对应系统验收;文件与命令工具也有各自的实现约束,不能把 Bash 沙箱概括成所有扩展工具都天然运行于同一 OS 隔离中。

本站展示了什么

“修改文档”场景展示允许、拒绝、后续同类操作不再询问以及取消后的审批失效。这里的文件完全位于浏览器本地存储,不是 OS 沙箱的替代品,也不证明真实终端命令在任意系统上都受隔离。

可观察的重点是拒绝后文件不变、批准后读取得到修改内容、停止后旧审批不起作用。浏览器内虚拟 README 的变化只是验证交互与状态,真实受保护路径和命令边界应通过运行时测试确认。