Repository navigation
fix(tools): \\?\ 扩展路径按普通写法判断授权根与权限规则;进程与终端按会话归属 - #82
Merged
AlphaCatMeow merged 6 commits intoNov 3, 2026
Merged
AlphaCatMeow merged 6 commits into
AlphaCatMeow merged 6 commits into
Conversation
\\?\D:\... 与 D:\... 是同一个文件,但 Go 把 \\?\D: 当作另一个卷, filepath.Rel 无法关联两种写法:模型照抄截图工具返回的扩展路径时 Image/Read/Write 被判越界;只读根用扩展写法配置时,普通写法的写入 跳过只读否决;deny 规则也漏掉扩展写法。 新增 internal/winpath:严格校验后把 \\?\X:\ 与 \\?\UNC\server\share\ 还原成普通写法,含义会变的写法与 \\.\、\??\、卷 GUID、GLOBALROOT 拒绝。liveagentPath、TUI read/write/edit 在 gate 之前统一规范化; safeWorkspacePath 两侧、sameDirectory、权限规则的请求路径/项目根/ 规则前缀、文件锁键同步处理。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
进程与终端管理器按会话存在、跨运行保留,但归属检查要求 runID 相同: 上一轮 Bash yield_time_ms 留下的 session_id,下一轮 ProcessWait 报 "managed process belongs to another canonical run";isolated 进程跨轮 后无法停止,无 id 的 status 列表也会悄悄隐藏它们。 新增 sharesConversation:同一会话的任何运行都可查看、等待、停止; 其他会话与没有运行身份的调用仍拒绝,创建运行留在记录上。ManagedProcess /ProcessWait/ProcessStop、终端读取与列表共用这一判定。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
请求一侧已把 \\?\UNC\host\share\... 还原成 \\host\share\...,规则一侧 只去掉了盘符前缀:Edit(\\?\UNC\host\share\dir/**) 或 Edit(//?/UNC/host/share/dir/**) 写成的 deny 规则什么都匹配不上。 trimExtendedPattern 同样把 UNC 前缀改写成 //。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
路径规则里反斜杠后跟 *?[] 一律当转义,D:\dir\** 被解析成 D:/dir\**, 只匹配名为 dir* 的文件,deny 静默失效。Windows 文件名不可能含 * 和 ?, 所以在 Windows 上 \* 和 \? 读作分隔符加通配符,\[ \] 仍是转义; Suggest 的 escapeGlob 同步只转义方括号,记住的规则读回来含义不变。 其他系统不变。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Nov 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
LiveAgent 里有两个独立的报错,修复都在
internal/tools的同一类检查上:\\?\D:\...\pilot-entry.png原样交给 Image,报Image.path is outside the authorized workspace roots。原因是 Go 把\\?\D:当成和D:不同的卷,safeWorkspacePath里的filepath.Rel在两种写法之间报错。同一个原因还导致:只读根用\\?\写法配置时,写入会跳过只读否决;deny 规则漏掉扩展写法。yield_time_ms留下的session_id,下一轮ProcessWait报managed process belongs to another canonical run。原因是进程和终端管理器按会话存在、跨运行保留,但归属检查要求 runID 也相同。Closes #80
Closes #81
改动
internal/winpath):Normalize严格校验后把\\?\X:\...还原成X:\...,把\\?\UNC\server\share\...还原成\\server\share\...。还原后含义会变的写法(.、..、/、空组件、末尾的点或空格、:流、保留设备名),以及\\.\、\??\、卷 GUID、GLOBALROOT,直接拒绝。Simplify用于已经信任的根,拒绝的写法原样返回。纯字符串处理,非 Windows 不做任何事。\\?\写法的合法路径被判越界;只读根用\\?\写法时,普通写法的写入被放行。现在:两种写法在越界判断、只读否决、权限检查和读写里都是同一条路径。liveagentPath和 TUI 的 read/write/edit 在 gate 之前统一走resolveFilePath;safeWorkspacePath两侧(覆盖授权根、只读否决、skill 根、named root、临时目录兜底)、named root 的 grant、sameDirectory、write/edit 的 GateRequest、文件锁键canonicalPathKey。internal/permissions):请求路径和项目根按普通写法匹配;规则本身写成\\?\D:/...、\\?\UNC\host\share/...、//?/UNC/...时,解析阶段改写成普通写法。以前这些 deny 规则匹配不上任何请求。slashPath、escapeGlob):以前反斜杠后跟*?[]一律当转义,Windows 上写成D:\dir\**、src\*.go的规则被解析成D:/dir\**,只匹配名为dir*的文件,deny 静默失效。Windows 文件名不可能含*和?,所以在 Windows 上\*、\?读作分隔符加通配符,\[、\]仍是转义;Suggest 的escapeGlob同步只转义方括号。旧版本存下的D:/dir\**重新解析后即生效。其他系统不变。限制:反斜杠写法下的方括号目录(D:\app\[id]\**)仍有歧义,需写成D:/app/\[id\]/**,与 Suggest 生成的形式一致。sharesConversation。同一会话的任何运行都可以查看、等待、停止之前运行启动的进程和终端;其他会话、没有运行身份的调用仍然拒绝;创建运行留在记录上。ManagedProcess、ProcessWait、ProcessStop、终端读取与列表共用这一判定。普通进程仍随启动它的运行结束而取消(读到的是cancelled)。docs/liveagent-backend.md补充进程终端按会话归属,以及 Windows 路径写法。契约面
\\.\等命名空间写法报unsupported Windows path namespace。终端 HTTP 入口的ownedSession现在按会话判断,同一会话任何已接受的运行都能看到该会话的终端cmd/knapproval/run.go的 owned 集合仍按运行记录,跨轮轮询会走一次 AI 复核(以前是直接被拒,不算回归)belongs to another canonical run→belongs to another conversation。LiveAgent 与 K-brain 里没有代码匹配旧文案docs/liveagent-backend.md验证
go build ./...、改动包go vet、git diff --check通过;复审另在GOOS=linux、GOOS=darwin下对 winpath/permissions/agent/tools 跑go vet,rc=0。internal/winpath/winpath_test.go:10 种还原写法、25 种拒绝写法、Simplify 对拒绝写法原样返回、非 Windows 不变。internal/tools/liveagent_windows_path_test.go:根与目标"带前缀 / 不带前缀"四种组合加小写盘符和相对路径;17 种命名空间与畸形写法被拒;同前缀兄弟目录、根外、只读根否决;报告里那次 Image 调用原样重放且 gate 看到普通写法;超过 260 字符的长路径实际可读;sameDirectory。修改前只读根用例返回 nil(写入被放行)。internal/tools/liveagent_windows_unc_test.go:\\?\UNC\工作区的相对路径、根自身写法、进程默认 cwd;UNC 只读根否决;TUI write/edit 对 5 种写法都不越过 deny;扩展 UNC 的 Image 在 gate 前不触发 SMB 访问(fix(tools): Image 按内容识别来源、跳过空占位并去重,可显示临时目录里的图片 #79 契约的扩展写法版);扩展 UNC 写法的 deny 规则。internal/permissions/windows_path_test.go、windows_unc_pattern_test.go:规则与请求各种写法组合下 deny 命中;前缀边界输入不越界、\\?\UNCx不被放宽。internal/agent/filelocks_windows_path_test.go:两种写法共用一把文件锁。internal/tools/liveagent_process_test.go:TestBashSessionOutputReadableInLaterRun精确复现报告里的报错(修改前输出managed process belongs to another canonical run);TestManagedProcessCanonicalOwnershipAndReadPolicy改为同会话后续运行可读、可列、可停,其他会话与无身份仍拒绝。terminal_test.go同步。\\?\UNC\工作区回归、UNC 只读根被绕过、TUI write/edit 用\\.\///?/绕过 deny);第 2 轮 1 个 P2(扩展 UNC 写法的 deny 规则匹配不上),全部修复;第 3 轮"未发现阻止合并的问题"。复审写的回归都保留在上述测试文件中。go test ./...:45 个包通过,失败 6 个,均为 Windows 已知基线(TestBackendQueueFIFOInterruptAndShutdown、TestCompactThresholdExplicitOverride、TestFilesystemRootConfinementAndText、TestPersistenceCASIdempotencyAndRollback、TestRestoreSessionPreservesHistoryAndCacheIdentity、TestWaitingOnSubagentsDuringForegroundSubagent)。cmd/kn的TestBackendCLIExecutableIntegration在本机挂起 40 分钟后手动结束,与 fix(tools): Image 按内容识别来源、跳过空占位并去重,可显示临时目录里的图片 #79 记录的本机基线一致,以 CI 为准。-race -count=10,按包单独跑):internal/winpath、internal/permissions、internal/tools通过;internal/agent20 次失败全部来自两个已知基线(TestCompactThresholdExplicitOverride ×10、TestWaitingOnSubagentsDuringForegroundSubagent ×10),无 data race。Image,sources:["\\?\D:\Documents\Projects\Web\LiveAgent\.codex-artifacts\...\pilot-entry.png"]:返回Display image,对话里显示 1440×1013 的截图(改前报越界)。yield_time_ms=1留下bash-1793633319242412900后结束;第 2 轮(另一个运行)ProcessWait同一 session_id:返回status=cancelled、exit_code=1(改前报belongs to another canonical run)。internal/permissions/windows_glob_rule_test.go覆盖D:\work\**、*.go、?.txt、**\*.env、相对src\**、UNC 与\\?\前缀,deny 与 allow 都测,另测通配范围不外溢、Suggest 形式的\[id\]仍为字面;修改前 deny/allow 全部不命中。对抗复审 2 轮,无 P1/P2,复审补的review_glob_extended_test.go、review_escapeglob_r2_test.go保留(Suggest 三个分支往返、AddRule 去重、POSIX 下\*仍是字面)。全量结果同上(45 包通过、6 个已知基线、cmd/kn本机超时);internal/permissions-race -count=10通过;GOOS=linuxvet 与编译通过。ModeIrregular,safeWorkspacePath只拒ModeSymlink)。这是预期行为,用户在工作区里建 junction 就是为了让工具读到目标目录(例如 pnpm 的node_modules),本 PR 不改。🤖 Generated with Claude Code