Skip to content

fix(permissions): 读取本会话进程输出按只读放行,扩充只读命令,堵住读取环境变量的只读放行 - #76

Merged
AlphaCatMeow merged 1 commit into
Stack-Cairn:mainfrom
AlphaCatMeow:fix/readonly-polls
Nov 1, 2026
Merged

AlphaCatMeow merged 1 commit into
Stack-Cairn:mainfrom
AlphaCatMeow:fix/readonly-polls

Conversation

@AlphaCatMeow

Copy link
Copy Markdown
Collaborator

LiveAgent 在 normal(始终询问)模式下实测:只读命令本身已放行,但模型取后台命令结果用的 ProcessWait 每次都询问,常见只读命令(hostname、--version、git tag 等)不在白名单;同时 echo $OPENAI_API_KEY、Get-Content Env:X、cat /proc/self/environ 这类写法会按只读把环境变量里的密钥直接读给模型。本 PR 让"查看本会话进程/终端输出"按只读放行、扩充白名单,并堵住读取密钥与在不受信仓库里运行 git 的只读放行。

Closes #75
Refs #71

改动

  • 进程/终端输出查看(Poll):ProcessWait、ManagedProcess 的 status/read_log/wait、ReadTerminal 改经 tools.AuthorizePoll 门控,GateRequest.Poll → permissions.Request.Poll(backend、TUI、ACP 透传)。以前按 shell 命令判定进程 id、每次询问 → 现在先 deny 规则、再 allow 规则(按 id 文本匹配),开启只读放行时按只读放行并发 permission.auto_resolved;Suggest 不生成规则。工具在门控后仍用 getOwned 校验归属。启动/停止进程、终端输入仍询问。GateRequestFor(AI 审查钩子)对这些动作以及 ProcessStop、ManagedProcess start 给出与工具相同的 Command。
  • 白名单扩充(只认安全形式):hostname(无参)、whoami、date(无参或 +格式)、Get-Date、Get-Process/gps、ps(不含 BSD e 与 -E)、Get-FileHash、显式工具链清单只带 --version(cmdlet 会把它当文件名)、git stash list|show、git tag(无参或 -l/--list)、git config --get|--get-all|--get-regexp|--list|-l、cd/Set-Location/pushd/popd 等、PowerShell 管道 Select-Object/Sort-Object/Measure-Object/Format-*/Out-String。
  • 只读放行收紧:含 $ 的变量展开;PowerShell 非文件提供者(Env:、Variable:、Function:、Alias:、Cert:、HKLM:、HKCU:、WSMan:,-Path:Env:X,Environment::/Registry:: 等提供者限定路径);/proc 下的 environ(含通配、/dev/fd、首层目录为通配的路径,以及 cd 进 proc 或通配目录之后的所有段);git stash 的 --output/--ext-diff。
  • 在另一个目录运行:cd 之后,以及 Bash / ManagedProcess start 的 cwd 参数指向工作目录以外(新标记 OtherDir)时,git 与 --version 不算只读,Suggest 也不建议记住规则(规则表达不了目录,记住 Bash(git status:*) 会在任何 cd 之后生效)。原因:git 读取所在仓库配置,core.fsmonitor、diff.external 会运行程序;工具链会按目录配置选二进制。git -C 保持 KB-1 的不放行。
  • docs/liveagent-backend.md 补充上述规则;KB-2 测试里代表"需要询问"的 hostname/whoami 换成 git --help/git help -a。

契约面

面 影响
backend HTTP 无协议字段变化;更多调用以 permission.auto_resolved{source:"read_only"} 放行,少数原先放行的写法(变量、提供者路径、/proc environ、cd 或 cwd 之后的 git)改为 permission.requested
TUI / ACP 同一引擎,行为同上;ACP 对 Poll 不提供 allow-always
AI 审查 GateRequestFor 与工具门控对同一调用给出相同 Command/Poll/OtherDir
已有 deny 规则 仍优先;Poll 按 id 文本匹配(ProcessWait(bash-:*) 前缀形式可用),ManagedProcess start 仍按命令匹配

验证

  • 基线:origin/main 5cd322b。
  • 静态:gofmt(LF 副本)、go vet ./internal/... ./cmd/...、git diff --check 通过。本机 golangci-lint 版本低于 go.mod,依赖 CI。
  • 新增测试(先失败后通过):
    • internal/permissions/readonly_kb3_test.go:白名单与边界(改前 33 条只读写法被判询问、13 条读密钥写法被放行)、Poll 的 deny/allow/只读、cd 与 OtherDir、/proc、ps、--version、Suggest 不记住 cd 之后的 git。
    • internal/tools/readonly_poll_test.go:各工具动作的门控请求带/不带 Poll;GateRequestFor 一致;Bash/ManagedProcess 的 cwd 置 OtherDir(""、.、根目录为否,子目录为是)。
    • internal/backend/readonly_poll_http_test.go:真实 HTTP 后端,模型先 Bash(yield_time_ms)再 ProcessWait,零询问、两次 auto_resolved read_only(改前 ProcessWait 询问)。
  • 对抗复审 4 轮:第 1 轮 2 P1 / 2 P2(cd→git 只在测试用函数里生效,生产路径未检查;git stash --output/--ext-diff;-Path:Env:X/Environment:: 绕过;cmdlet 的 --version 写文件),第 2 轮 3 P2(cd 之后建议记住 git 规则;/proc 通配与 cd 绕过;ps -E),第 3 轮 1 P1 / 1 P2(Bash cwd 参数绕过;不出现 proc 字样的 /proc 写法),全部修复;第 4 轮"未发现阻止合并的问题"。复审写的回归保留在 review_kb3_*_test.go(17 个),全部通过;其中用本机 git/pwsh/bash 实测的部分在缺少该工具时跳过,断言本身不依赖。
  • 全量(kb-full-tests.sh):45 个包通过,失败 6 个,均为 known-failures.json 的 Windows 基线(TestBackendQueueFIFOInterruptAndShutdown、TestCompactThresholdExplicitOverride、TestFilesystemRootConfinementAndText、TestPersistenceCASIdempotencyAndRollback、TestRestoreSessionPreservesHistoryAndCacheIdentity、TestWaitingOnSubagentsDuringForegroundSubagent)。
  • race(acp/backend/permissions/tools/tui,-race -count=10):无 DATA RACE,仅基线用例失败。
  • 说明:全量启动后我又把 environ 判定从"含 environ 即询问"放宽为"environ 出现在路径中才询问"(不误伤 rg os.environ),只改 permissions 包;改后单独重跑 permissions/tools/backend 通过。
  • 真机(Windows,LiveAgent 调试版 + 本分支本地编译 sidecar,normal 模式,同一组 5 段提示词经 MCP bridge 自动执行,审批结果以后端事件日志核对):
组 beta.27 询问次数 本 PR
1 Read/List/Glob/Grep 0 0
2 白名单命令 10 条 10(全是 ProcessWait) 0(10 次 ProcessWait 均 auto_resolved read_only)
3 清单外命令 15 条 29(15 命令 + 14 ProcessWait) 3:git -C crates status、cd crates; git status、Get-ChildItem Env: —— 均为设计上应询问
4 进程/终端 6 2:ManagedProcess start、TerminalSession —— 应询问;ProcessWait、status、read_log、ReadTerminal 放行
5 对照(写文件、git stash、npm install) 3,全部拒绝 3,全部拒绝;工作区未改动
  • 未覆盖:Linux/macOS 只在 CI;ps e/-E 的 BSD/macOS 行为依据手册未实测;rustup、yarn 本机未安装,按目录选二进制的情况只做代码层确认;只读命令不限项目根(cat ~/.ssh/id_rsa 仍放行)是 KB-1 的既定策略,本 PR 未改。

🤖 Generated with Claude Code

- ProcessWait、ManagedProcess status/read_log/wait、ReadTerminal 经新的
  tools.AuthorizePoll 门控,GateRequest/permissions.Request 带 Poll:先 deny 规则,
  再 allow 规则,开启只读放行时按只读放行,不生成可记住的规则;GateRequestFor
  对这些动作与 ProcessStop、ManagedProcess start 给出与工具一致的 Command
- 只读白名单补上 hostname(无参)、whoami、date(无参或 +格式)、Get-Date、
  Get-Process、ps(不含打印环境的 e/-E)、Get-FileHash、常见工具链只带 --version、
  git stash list/show、git tag(无参或 -l)、git config --get/--list、cd 类命令与
  PowerShell 管道的筛选/排版 cmdlet
- 只读放行收紧:含 $ 的变量展开、PowerShell 非文件提供者(Env:、Variable:、
  -Path:Env:X、Environment:: 等)、/proc 下的 environ(含通配与 /dev/fd 写法)、
  git stash 的 --output/--ext-diff 都改为询问
- 在另一个目录运行(cd 之后、Bash/ManagedProcess 的 cwd 参数,标记 OtherDir)时,
  git 与 --version 不算只读,也不建议记住规则:它们读取所在目录的配置,可能运行程序
- KB-2 测试中代表"需要询问"的 hostname/whoami 换成 git --help / git help -a

Closes Stack-Cairn#75

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@AlphaCatMeow
AlphaCatMeow merged commit 0d84c41 into Stack-Cairn:main Nov 1, 2026
4 checks passed
@AlphaCatMeow
AlphaCatMeow deleted the fix/readonly-polls branch November 1, 2026 07:49
AlphaCatMeow added a commit to Stack-Cairn/LiveAgent that referenced this pull request Nov 1, 2026
kbrain.lock.json 升级到 v0.107.6-beta.28(Stack-Cairn/K-brain main 0d84c41),
包含进程/终端输出只读放行与只读判定收紧(Stack-Cairn/K-brain#76)。

Closes #1095

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

权限:读取本会话进程输出仍询问、常见只读命令缺失,且只读放行能读出环境变量密钥

1 participant