护栏
护栏是 Bromure Agentic Coding 在宿主机侧对工作区凭据使用方式进行的控制。正如该窗格自身所述:护栏管理此工作区已配置凭据的使用方式。使用前询问会在会话中首次使用某个凭据时弹出宿主机侧的确认。写入策略会在传输过程中剥离或阻止破坏性操作——由代理服务器强制执行,因此虚拟机中被入侵的代理无法绕过它。只有你已配置的凭据才会显示在这里。
该窗格为每个已配置凭据显示一行,其顺序与凭据窗格中列出的顺序一致。每一行显示凭据的标题和宿主机,并带有两个控件:
- 一个使用前询问复选框(控件本身标注为需要批准才能使用)——每个凭据的许可关卡,从凭据窗格移至此处。
- 一个内嵌的写入策略选择器,仅在凭据对应的服务支持时显示。
如果工作区没有凭据,该窗格会显示空状态——没有可保护的凭据——引导你返回凭据窗格。强制执行细节、错误格式和审计追踪记录在提示注入与护栏深入解析中有介绍。
使用前询问
每一行都有一个使用前询问复选框,默认关闭。当它开启时,在会话中首次使用该凭据时,代理服务器会暂停并弹出一个许可对话框,提供有时限的授权——5 分钟、1 小时,或本会话剩余时间——或不允许。授权仅存于内存中,会在会话窗口关闭时被清除,每个实时决策都会列在**窗口 → 凭据批准…**中。许可模型、并发提示的合并处理以及批准窗口在凭据与传输边界中有介绍。
此复选框适用于任何凭据,包括纯 API 密钥、SSH 密钥和手动令牌——没有写入策略的行只显示此控件。
写入策略
当凭据对应的服务能够对自身流量进行分类时,该行还会显示一个写入策略选择器。它会在以下情况下出现:
- Git 代码托管平台——GitHub、GitLab、Bitbucket 令牌。
- AWS 凭据。
- DigitalOcean 令牌。
- 容器镜像仓库(Docker Hub、ghcr.io 等)。
- Kubernetes 上下文。
- 数据库端点(MongoDB、ClickHouse、Elasticsearch)。
每种写入策略都提供相同的四种模式:
| 模式 | 行为 |
|---|---|
| 关闭 | 不进行过滤。 |
| 写入前提示 | 读取操作直接通过。每次写入都会暂停,弹出宿主机侧的许可对话框,显示确切的操作,并提供有时限的授权(见下文)。 |
| 阻止破坏性操作 | 删除、drop 和终止操作被阻止;创建和更新操作通过。 |
| 只读 | 每次变更都被阻止;只有读取操作通过。 |
新工作区在每个支持策略的服务上默认使用写入前提示(通过偏好设置模板)。在护栏功能存在之前创建的工作区——或 JSON 中省略了该字段的配置文件——会被解码为关闭。
注意: 写入策略是按服务的,而非按凭据。同一服务的两个凭据——比如两个 GitHub 令牌——共享一个策略,因此在任一行更改选择器都会同时更改两者。
注意: 护栏对操作进行分类;它不隐藏凭据。凭据本身仍会按凭据下的配置由代理服务器注入和替换。将只读写入策略与同一行的使用前询问复选框结合使用,可实现纵深防御。
各服务如何对调用进行分类
| 服务 | 范围 | 分类 |
|---|---|---|
| Kubernetes | 来自此工作区 kubeconfig 的 Kubernetes API 服务器 | GET/HEAD/OPTIONS = 读取;DELETE = 破坏性(包括 deletecollection);其他动词 = 写入。被阻止的调用会返回一个 Kubernetes Status 403 JSON,kubectl 能够清晰地呈现它。 |
| AWS | 所有 *.amazonaws.com 宿主机 | 来自 X-Amz-Target 请求头的操作名称(如 DynamoDB 和 Lambda 等 JSON 协议服务)或 Action= 表单参数(如 EC2、IAM、SQS 等查询协议服务)按前缀分类:Delete*/Terminate*/Remove*/Purge*/Destroy*/Deregister*/Revoke* = 破坏性;Get*/List*/Describe* 及类似前缀 = 读取。对于 S3 和 REST 风格的请求,则回退到使用 HTTP 方法。被阻止的调用会返回一个 AccessDeniedException 主体。 |
| DigitalOcean | api.digitalocean.com 和 *.digitalocean.com | HTTP 方法:DELETE = 破坏性;GET/HEAD = 读取。 |
| 容器镜像仓库 | 在凭据下配置的镜像仓库,以及 Docker Hub 端点 | 拉取(GET)= 读取;推送(PUT/POST)= 写入;DELETE = 破坏性。被阻止的调用会返回一个镜像仓库风格的 DENIED 错误主体。 |
| GitHub | github.com REST API 和基于 HTTPS 的 git | REST 基于方法。git push(git-receive-pack)算作写入——在只读下被阻止,在写入前提示下会提示;git fetch(git-upload-pack)始终为读取。 |
| GitLab | gitlab.com REST API 和基于 HTTPS 的 git | 与 GitHub 相同的分类逻辑。 |
| Bitbucket | bitbucket.org REST API 和基于 HTTPS 的 git | 与 GitHub 相同的分类逻辑。 |
数据库端点按引擎进行分类:
| 引擎 | 读取 | 写入 | 破坏性 |
|---|---|---|---|
| MongoDB (Atlas Data API) | find、findOne、aggregate | insert、update、replace | deleteOne、deleteMany |
| ClickHouse | 以 SELECT、SHOW、DESCRIBE、EXPLAIN、WITH 等为首关键字的 SQL … | INSERT、CREATE、ALTER … | DROP、TRUNCATE、DELETE,以及 ALTER … DELETE / DROP COLUMN / DROP PARTITION / CLEAR |
| Elasticsearch | _search、_msearch、_count、_mget、_sql 以及其他查询端点(即使通过 POST) | _bulk、_update、文档索引 | DELETE 和 _delete_by_query |
当设置了某个策略但没有可供其应用范围的对象时——Kubernetes 上下文没有 kubeconfig、数据库端点没有设置宿主机——会出现橙色内嵌警告,因为此时护栏没有可应用的宿主机。
注意: 对于 ClickHouse,如果请求中看不到 SQL 文本,只读会阻止该请求(Bromure 无法证明它是读取),而阻止破坏性操作会放行(它采取放行的默认策略)。
许可对话框(写入前提示)
在写入前提示模式下,读取操作静默通过,每次写入都会暂停并弹出一个标题为 Allow write on "<scope>" from workspace "<name>"? 的宿主机对话框。对话框主体逐字显示确切的操作——数据库的字面 SQL 语句,或 REST 调用的 METHOD /path——因此你批准的是实际将要运行的内容,而非摘要。按钮包括:
- 允许 15 分钟(默认按钮)
- 允许一次——刻意不创建任何授权,因此紧接着的下一次写入会重新提示。适用于对一个话痨的代理逐次写入进行审计。
- 允许本会话剩余时间
- 不允许——代理会收到与阻止模式所产生的相同的硬错误。该拒绝会被记住 60 秒,这样循环重试同一次写入的代理不会每秒都重新提示。
授权按工作区和协议范围划定:一个 Kubernetes API 宿主机、整个 AWS、一个容器镜像仓库、每个 git 代码托管平台整体,或一个数据库宿主机。在一个宿主机上允许 ClickHouse 写入不会在其他任何地方授予任何权限。并发的相同写入会合并到单个对话框上,所有决策仅存于内存中——会话范围的授权会在会话拆除时被清除。
当工作区通过 SSH 或 CLI 以无界面方式驱动时,相同的四个选项会作为文本提示出现在工作区的 tmux 中;不回答即视为拒绝。
注意: 护栏的写入授权不会列在任何窗口中。凭据批准窗口(窗口菜单 → 凭据批准…)仅显示凭据许可决策——即使用前询问的授权;写入策略授权会按其自身的时钟或在会话拆除时到期。
调用被阻止时代理看到的内容
被阻止的调用会返回一个协议相应的 403 风格错误主体——Kubernetes Status JSON、AWS AccessDeniedException、镜像仓库 DENIED 载荷——其消息以 "blocked by Bromure Guardrails" 结尾。代理看到的是一个可以报告的干净、普通的 API 失败,而非一个挂起的连接。(供应链阻止改用 HTTP 451,正是为了让两者一眼就能区分——见供应链。)