Skip to content

🔒 补齐 cp 文件传输审批:upload_file/download_file 与 opsctl cp 不再绕过 - #251

Merged
CodFrm merged 8 commits into
mainfrom
worktree-fix-cp-approval
Jul 21, 2026
Merged

🔒 补齐 cp 文件传输审批:upload_file/download_file 与 opsctl cp 不再绕过#251
CodFrm merged 8 commits into
mainfrom
worktree-fix-cp-approval

Conversation

@CodFrm

@CodFrm CodFrm commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

背景

upload_file / download_fileopsctl cp 在整条路径上没有任何审批检查——模型对同一台 SSH 资产,走 exec 需要审批,走 upload_file 不需要。而写文件足以等价于执行命令(~/.ssh/authorized_keys/etc/cron.d/*、任何被 systemd/CI 引用的脚本路径)。

cp 其实早就是一等审批类型,只是从来没有调用点发起过:

  • internal/approval/approval.gointernal/ai/permission/approval.go 的 Type 枚举里都写着 "cp"
  • grant_entity.Grant.ToolName 注释是 "exec", "cp", "create", "update"opsctl grant 的 CLI 帮助也允许用户建 type=cp 的授权——建了没人查
  • requireApproval 的离线分支专门处理 cp
  • opsctl help 一直在写 "Write operations (exec, cp, create, update) require desktop app approval"
  • cp.go 里是一句 // cp 不需要审批

所以这个 PR 不是新增机制,是把那条没写完的分支补齐。

改动

  1. policy.MatchPathRule — 路径 glob(* 不跨 /)的唯一实现,local_write/local_edit 的门禁改调它,与 cp 共用同一套语义。
  2. grant 池按工具面隔离SaveGrantPattern 开始写入真实 tool_name;匹配时 cp 与非 cp 互不可见。这是前置条件:否则用户在 cp 审批里把 pattern 编辑成 *(很常见),这条路径授权会被命令匹配器看见,放行该资产上的任意命令。只在 cp/非 cp 之间划线而不按类型严格相等,是因为存量行的 tool_name 一律被旧版写死成 "exec"(含 redis/sql),严格相等会让存量会话授权集体失效。
  3. 注册 cp 权限类型 — 只查 grant,不查 CommandPolicy 的 allow/deny 规则(那些是命令形状的,拿路径去撞只会误判);审批项支持 detail
  4. AI 两个工具 — 在 ExecuteWithSFTP 之前过审批,主体是远端路径,本地路径与方向进 detail。
  5. opsctl cp — 审批放在 proxy 与直连分支的共同上游(否则 proxy 路径会漏),资产间传输审两次(源端读 + 目的端写),审计从传 nil 改成传真实决策。
  6. 审批面板cp 图标 + detail 展开不再限定本地工具。

验证

  • go test ./... 全绿;改动包 golangci-lint 0 issue;前端 lint 0 error
  • 真机观测:隔离数据目录 + 桌面端不在线时跑 opsctl cp,返回 desktop app is not runningaudit_logs 留下 tool_name=cp 的拒绝记录,没有发生任何 SFTP 连接
  • AI 侧复现:加门禁前 handleUploadFile 报的是 获取SSH配置失败: SSH配置为空——已经在拨 SSH,审批回调一次没调
  • 隔离测试做过反证:去掉过滤后两个方向都以正确理由失败;opsctl cp 的用例补了"批准后照常传输"防止 called=false 是假绿

遗留

存量 grant 行的 tool_name 仍是 "exec"。要收紧成按类型严格相等,需要配一次 backfill 迁移,而 group 级授权(可跨资产类型)本身没有唯一正确值——建议另开 issue。

closes #248

@CodFrm
CodFrm merged commit 7b87c92 into main Jul 21, 2026
5 checks passed
@CodFrm
CodFrm deleted the worktree-fix-cp-approval branch July 21, 2026 13:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🔒 upload_file / download_file 完全绕过审批检查

1 participant