已关闭
bug(pr): pr checkout 的 fetchURLHost 误解析 IPv6 字面量 clone URL #298
zhaoxufeng创建于  6月15日关闭于  6月24日
zhaoxufeng
zhaoxufeng
6月15日 创建

问题现象

gc pr checkout 在 PR #240 引入的 fetchURLHost(pkg/cmd/pr/checkout/checkout.go)从 clone URL 的 authority 中提取 host 时,按第一个 : 截断端口。对 IPv6 字面量 URL(如 ssh://[::1]:22/owner/repo.git)会把 host 误解析为 [,而非 ::1。

复现步骤

  1. 设想 / 构造一个 head repo clone URL 为 IPv6 字面量形式:ssh://[::1]:22/owner/repo.git。
  2. 进入 validateFetchURL → fetchURLHost("[::1]:22/owner/repo.git")。
  3. 先按 / 截断得到 [::1]:22,再按第一个 : 截断得到 [。

期望行为

IPv6 字面量的 host 应解析为 ::1(即识别 [...] 包裹,端口分割只在 ] 之后或无括号时按 : 处理)。

实际行为

host 被解析为 [。

影响范围

  • 命令:gc pr checkout(fallback fetch-from-head-repo 路径)
  • 安全无影响:[ 不以 - 开头、非空,dash-host 注入防护仍然生效;完整 URL 仍原样交给 git。
  • 可用性 quirk:仅当 GitCode 真实返回 IPv6 字面量 clone URL 时,可能出现「合法 URL 被 host 校验误判」的边缘问题。概率极低。

补充信息

  • 严重度:低(minor / 边缘场景)
  • 源自 PR #240 多角色评审「边界条件」角色发现(评为 harmless quirk,非阻塞)
  • 修复建议:fetchURLHost 端口分割改为「仅在最后一个 ] 之后或无括号时按 : 截断」,并补一条 IPv6 测试用例固化预期
  • 关联:#293 / PR #240
likedislike
aflyingto成员
6月24日 评论:

验证记录

  • 验证版本: main 分支 (24ddf9f),PR #240 分支 diff 中的 fetchURLHost 函数
  • 复现命令: 模拟 fetchURLHost 逻辑,输入 ssh://[::1]:22/owner/repo.git → authority [::1]:22 → 按第一个 : 截断 → host = [
  • 实际结果:
    • ssh://[::1]:22/owner/repo.git → host 被解析为 [(期望 ::1)
    • ssh://[2001:db8::1]:2222/owner/repo.git → host 被解析为 [2001(期望 2001:db8::1)
    • 非 IPv6 用例(gitcode.com:22、gitcode.com)不受影响
  • 根因: fetchURLHost 在端口分割时使用 strings.IndexByte(host, :) 取第一个 :,对 IPv6 字面量 [::1]:22 会错误截断在 [ 之后
  • 修复方向: 识别 [...] 包裹 → 取括号内内容作为 host → 仅在 ] 之后或无括号时按 : 截断端口
  • 结论: 问题仍存在,确认有效,进入修复
  • 严重度: 低(边缘场景,仅当 GitCode 返回 IPv6 字面量 clone URL 时触发)
likedislike
Aaflyingto成员
6月24日 添加了label:risk/lowscope/pr, status/verified,type/bug
aflyingto成员
6月24日 评论:

作者自检

  • 作者主体标识: Claude Fable 5 (via aflyingto)
  • 根因或实现理由:
    • #298: fetchURLHost 使用 IndexByte(:) 取第一个 : 截断端口,对 IPv6 字面量 [::1]:22 错误截断在 [。修复:识别 [...] 括号 → 返回括号内地址 → 仅在 ] 之后或非括号时按 : 截断
    • #302: TestResolveRunMissingRepo 使用真实 HTTP client,CI 无 GC_TOKEN 导致认证阶段失败,"no repository" 检查未执行。修复:t.Setenv("GC_TOKEN", "dummy-token")
  • 主要修改:
    • pkg/cmd/pr/checkout/checkout.go: 新增 fetchURLHost + scpHost(+38行),修复 IPv6 解析
    • pkg/cmd/pr/checkout/checkout_test.go: 新增 TestFetchURLHost(9用例,含4个IPv6)+ TestScpHost(2用例)
    • pkg/cmd/pr/comment/resolve/resolve_test.go: +1行 t.Setenv("GC_TOKEN", "dummy-token")
  • 单元测试: 1187 passed in 95 packages(本地)✅
  • 构建: go build -o ./gc ./cmd/gc Success ✅
  • CI验证: https://github.com/gitcode-cli/cli/actions/runs/28071396966 — All 8 jobs success ✅
    • Lint ✅ | Test (3 OS) ✅ | Build (3 OS) ✅ | Docker ✅
  • 安全审查:
    • git diff 无硬编码 token/password/secret ✅
    • 改动不涉及认证/配置/权限敏感路径 ✅
    • dummy-token 仅在测试中使用,非真实凭证 ✅
  • 文档同步: 本次为 bugfix,无命令行为变更,无需更新 COMMANDS.md ✅
  • 风险: risk/low — 修复仅影响边缘 IPv6 场景 + 测试环境 token 配置
  • 未覆盖项:
    • 真实 IPv6 GitCode clone URL 场景无法构造(#298 为边缘 case)
    • comment/resolve 包其他 CI 失败测试(#302)未全部修复,仅修复 TestResolveRunMissingRepo
likedislike
Aaflyingto成员
6月24日 添加了label:status/in-progress
Aaflyingto成员
6月24日 添加了label:status/self-checked
Aaflyingto成员
6月24日 关联了pull request:fix(pr): fix fetchURLHost IPv6 parsing + CI test auth
Aaflyingto成员
6月24日 关闭了 issue
Aaflyingto成员
6月24日 添加了label:status/merged