Repository navigation
fix(capability): detect native and escaped Windows private paths in public-safe-outbound - #6223
Conversation
… for agent-v5r2 claim Signed-off-by: JasonBuildAI <jasonbuildai@gmail.com>
1f8b351 to
a5de384
Compare
…ublic-safe-outbound The builtin fail-closed pre-submission scrub only recognized the POSIX spelling of a private absolute path. On a Windows host the same private path written as C:\Users\<name>\... or \\server\Users\<name>\..., and the escaped form a serialized string produces (C:\\Users\\<name>\\...), passed the scan with hit_count 0 while its POSIX spelling was blocked. loopx-project#6161 repaired the same spelling class in the public/private boundary scan and names this rule as its deliberately deferred successor owner. Match a separator run at every junction of private_abs_path, covering the POSIX, native Windows, mixed, rooted and escaped spellings of the same roots, and pin the native, escaped and mixed forms with tests. Closes loopx-project#6220 Follow-up to loopx-project#6161 Signed-off-by: JasonBuildAI <jasonbuildai@gmail.com>
a5de384 to
ce83ba9
Compare
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; gpt-6.1-sol; OpenAI; runtime_reported; reasoning_effort=xhigh
详细中文评审 — #6223,exact head ce83ba927ddc27954ba3ae444f0bc452d6d86d29
动机
需要在公开发送前检查文本的操作者,尤其是从 Windows 源码环境导出内容的人。
同一份文档中的 POSIX 私人目录会被拦下,Windows 原生或 JSON 转义路径却会漏过,造成误以为扫描通过的风险;修复后这些拼写在原扫描入口被检出,普通公开路径仍可通过。
真实扫描目录中检出项由1项变成3项;仅含转义路径的 diff 从通过变成拒绝,扫描前后文件哈希保持一致。
本次只补齐分隔符拼写;不证明所有 Windows 路径形式均已覆盖,不改变发送权限,也不执行发送。
规格依据:loopx/capabilities/public_safe_outbound/README.md,pre-change adb247e5f3fac8e2e3f7152239955b49480d0b9f;映射项 existing-caller-invariant(本次评审标签,不是新增协议)。相关 issue/maintainer frame 与当前 caller 一并核对,PR 自述不是独立 oracle。
改动思路
继续复用既有 public_safe_outbound 扫描规则、配置和遮罩输出,只扩大同一私人根目录规则支持的分隔符;这是文本词法检测,不能当作操作系统路径或授权判断。
这项PR完成 issue #6220 的分隔符漏检修复;大小写、非 ASCII 用户名及末尾缺分隔符仍是原有边界,未宣称完成全部路径隐私检测。
具体改动
两处文件合计 +60/-2:scanner.py 保留私人根目录和用户名字符集合,把两侧分隔符改为 slash/backslash 的连续段;test_scanner.py 添加原生、转义与 UNC 回归。既有 _match_rule → scan_texts → scan_paths/scan_git_diff → scan_cli.main 仍负责命中、遮罩和退出码,没有发送动作或新权限。
独立检查13种拼写,并实际执行目录扫描和 stdin diff:目录正例包含原有 POSIX 控制,因此 base 是 exit1/hit1、head 是 exit1/hit3;单独转义 diff 才是 exit0→exit1。公开目录、普通文本和原 POSIX 行为保持。7项源码测试、Ruff、capability-extension-registry smoke、先 advisory 后全量 semantic 检查均通过。
对主干的风险
非阻塞 P2:词法规则也会拦截相对目录中同名的 Users 段,符合既有保守、宁可多报的扫描约定,操作者仍需要复核命中。issue #6220 明确把大小写兼容排除;非 ASCII 用户名、末尾缺分隔符也没有扩大覆盖。我在 macOS 上检查的是 Windows 文本拼写,未宣称 Windows 宿主实测。无配置、存储、quota 或生命周期改动,回滚不需要迁移。
我的整体评价
通过本次 exact-head 评审。长期效果正向证据是重复导出时同类私人路径不再静默漏检;体验收益是复用原命令即可发现问题,文件不被修改。保守匹配会增加部分人工复核,未测自然使用中的总成本。前瞻重构检查:当前单规则修复足够,若后续扩展规范化,可再与既有同类扫描共享一个有回归覆盖的词法 owner;本次不加框架。
English verdict: APPROVE — #6223 at ce83ba9. private_abs_path separator runs accept slash/backslash, escaped runs and mixed spelling; POSIX and public text preserved. Independently checked real source callers, negative/base-head controls and native validation; read-only actual CLI verified. No merge, release, authority or natural model-utility claim.
Goal And Delivered Outcome
Outcome basis / optional anchor: [Bug]: builtin public-safe-outbound scanner misses native Windows private paths (C:\Users\... and UNC) #6220
Goal/source and gap: The builtin
public-safe-outboundcapability is the fail-closed pre-submission scrub for content headed to an external repository. Itsprivate_abs_pathrule (loopx/capabilities/public_safe_outbound/scanner.py) recognized only one separator spelling of a private absolute path, so a Windows host's own spellings (C:\Users\<name>\...,\\server\Users\<name>\...) and the escaped form a serialized string produces (C:\\Users\\<name>\\...in JSON or a source literal) scanned clean while the POSIX spelling was blocked. fix(contract): block native, mixed and escaped Windows private paths in the boundary scan #6161 repaired the same spelling class in the repository's public/private boundary scan and names this rule as its deliberately deferred successor owner; this PR is that follow-up.Observable before → after, with the validation row that proves it: before, the native and escaped spellings returned
ok=Truewith no hits (CLI exit 0,hit_count 0), including a.jsonfile carrying the escaped path; after, every spelling reportsrule_id: "private_abs_path"and the CLI exits 1, while paths outside the private roots stay clean. See theregression_parityandreal_entrypointrows.Issue/task and intended base: Closes [Bug]: builtin public-safe-outbound scanner misses native Windows private paths (C:\Users\... and UNC) #6220. Base:
main.Author Declaration
Implemented against
loopx/capabilities/public_safe_outbound/scanner.py(private_abs_path)loopx/capabilities/public_safe_outbound/tests/test_scanner.py::test_detects_native_windows_private_pathC:\\Users\\<name>\\...) is a hit...::test_detects_escaped_and_mixed_windows_private_path...::test_native_windows_path_outside_the_private_roots_stay_cleanC:\users\...)/home/<non-ASCII-name>/)ruff checkon the capability, andexamples/capability-extension-registry-smoke.py, and compared the old and new rule on a 16-case matrix (POSIX hits and clean inputs unchanged). An independent review round reproduced one escaped-spelling miss in the first revision; this head fixes it and pins it with tests. Two environment-level issues are disclosed rather than hidden:tests/capabilities/test_capability_extension_registry.py::test_installed_runtime_is_catalog_truth_and_cli_defaultfails identically on the unmodified baseline (entrypoint_missing), and a host route conflict makesloopx checkunavailable in this checkout; neither is touched by this change.Scope And Continuation
private_abs_pathto one separator-run pattern that keeps the existing root keywords and covers the POSIX, native Windows, mixed, rooted and escaped spellings, plus tests; 60 lines added, 2 removed. Remaining: case-insensitive spellings and non-ASCII user names stay out of scope as disclosed above.Validation
ce83ba927ddc27954ba3ae444f0bc452d6d86d29regression_paritypassedok=False+private_abs_pathhit after beingok=True/0 hits on the old rule; all four POSIX spellings and the clean inputs unchanged (16-case matrix). Pre-fix test run: 1 failed / 5 passed (AssertionError: drive); after: 7 passed.real_entrypointpassedscan_cli(python -m loopx.capabilities.public_safe_outbound.scan_cli --scan-root ... --format json): a.jsonfile with the escaped path and a.mdwith the native path exit 0 /hit_count 0→ exit 1 /hit_count 3(escaped + native + POSIX control); a clean file is not hit.unitpassedloopx/capabilities/public_safe_outbound/tests/test_scanner.py: 7 passed.staticpassedruff check loopx/capabilities/public_safe_outbound: clean.integrationpassedexamples/capability-extension-registry-smoke.py: ok (capability registry unchanged).real_backendnot_applicableFrontend / Visual Evidence
Type of Change
LoopX Area
Technical Direction
Shared-authority RFC fixture impact
Boundary Checklist
.loopx/,.codex/goals/, and liveACTIVE_GOAL_STATE.md).none.Signed-off-bytrailer (git commit -s).