已关闭
bug(pr): pr checkout 的 fetchURLHost 误解析 IPv6 字面量 clone URL #298
zhaoxufeng创建于 6月15日关闭于 6月24日
aflyingto
6月24日 评论:
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 时触发)


aflyingto
6月24日 评论:
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")
- #298:
- 主要修改:
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/gcSuccess ✅ - 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


问题现象
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。复现步骤
ssh://[::1]:22/owner/repo.git。validateFetchURL→fetchURLHost("[::1]:22/owner/repo.git")。/截断得到[::1]:22,再按第一个:截断得到[。期望行为
IPv6 字面量的 host 应解析为
::1(即识别[...]包裹,端口分割只在]之后或无括号时按:处理)。实际行为
host 被解析为
[。影响范围
gc pr checkout(fallback fetch-from-head-repo 路径)[不以-开头、非空,dash-host 注入防护仍然生效;完整 URL 仍原样交给 git。补充信息
fetchURLHost端口分割改为「仅在最后一个]之后或无括号时按:截断」,并补一条 IPv6 测试用例固化预期