Skip to content

fix: strengthen Git repository URL validation (#22)#62

Merged
keting merged 11 commits intoketing:mainfrom
beautyarbutin:fix/22-strict-github-repo-validation
May 2, 2026
Merged

fix: strengthen Git repository URL validation (#22)#62
keting merged 11 commits intoketing:mainfrom
beautyarbutin:fix/22-strict-github-repo-validation

Conversation

@beautyarbutin
Copy link
Copy Markdown
Contributor

@beautyarbutin beautyarbutin commented Apr 29, 2026

Summary

Strengthen Git repository URL validation for project create/update flows.

This change is needed because invalid repository addresses, missing owner/repo paths, repository-internal page URLs, unsafe protocols, local/private network targets, query/fragment URLs, and embedded credentials could previously be saved as project repository URLs.

The change adds stricter Git remote URL validation on both backend and frontend. It accepts repository root URLs and clone URLs, including HTTPS, ssh://, and SCP-style Git URLs. It rejects missing-protocol inputs, missing repository path information, repository-internal pages, unsafe protocols or prefixes, query/fragment values, embedded credentials or tokens, leading-dash inputs, invalid hostnames, localhost/private/link-local/metadata targets, non-standard private IP forms, and IPv4-mapped private addresses.

For known Web Git hosts, validation now applies host-specific root path rules: GitHub, Gitee, Bitbucket, and Codeberg require a root owner/repo path when using a non-.git URL, while GitLab subgroup repository roots remain supported.

Project git_repo_url is now required for both create and update flows. Users cannot create a project without a repository URL or clear the repository URL on edit.

This PR validates URL shape and safety only. It does not perform remote repository reachability checks during project create/update, does not limit HALF to GitHub-only repositories, and does not automatically clean existing historical invalid repository URLs. If a repository is validly shaped but does not exist or cannot be accessed, the later polling/git clone step shows a user-facing access error and HALF retries automatically.

User-facing and architecture documentation were updated to describe the accepted URL forms, rejected URL forms, required repository URL behavior, private repository credential guidance, host-specific root path rules, and the fact that save-time validation does not verify repository existence.

Closes #22

Testing

  • python src\backend\tests\test_git_service.py
  • python src\backend\tests\test_project_agent_availability.py
  • python src\backend\tests\test_polling_service.py
  • python -m unittest discover -s src\backend\tests
  • cd src/frontend && npm test -- ProjectNewPage.test.ts
  • cd src/frontend && npm test
  • cd src/frontend && npm run build
  • CI 已通过

Checklist

  • The change stays scoped and focused.
  • Related issues are linked when applicable.
  • Docs were updated where behavior, API shape, or setup changed.
  • No secrets, private URLs, or local machine paths were introduced.

@beautyarbutin beautyarbutin requested a review from keting as a code owner April 29, 2026 15:03
@beautyarbutin beautyarbutin force-pushed the fix/22-strict-github-repo-validation branch from 1ebc191 to 3c3f023 Compare April 30, 2026 10:57
@beautyarbutin
Copy link
Copy Markdown
Contributor Author

根据 review 意见已更新本 PR,主要调整如下:

  • 移除了 create/update 保存项目时的 git ls-remote 可达性检查,避免保存流程依赖外部网络、仓库凭据或远端响应。
  • 删除了 docs/releases/2026-04-29-github-repo-url-validation.md,不再把单 PR 工作日志放入 release notes 目录。
  • 修复了前端 IPv6 ULA 判断误拒 fcc.comfdic.govgit.fcompany.com 等合法域名的问题。
  • 拒绝 HTTPS URL 中的 userinfo/token,例如 https://token@github.com/org/repo.git
  • 放宽 ssh:// 形式的安全用户名,支持部分自托管 Git 服务场景。
  • 调整测试,当前保存项目时只校验 Git remote URL 的格式和安全边界,不再验证仓库是否真实存在。

@beautyarbutin
Copy link
Copy Markdown
Contributor Author

beautyarbutin commented Apr 30, 2026

image 创建项目时填写的git仓库不存在/不可访问的情况:

创建项目:通过,因为 URL 格式合法
轮询仓库:失败,因为仓库不存在或不可访问
页面展示 Git sync failed

@beautyarbutin
Copy link
Copy Markdown
Contributor Author

image 创建项目时填写的git仓库URL明显不合规的情况,会出现提示且禁止更新项目。

@keting keting self-requested a review May 1, 2026 02:36
Copy link
Copy Markdown
Owner

@keting keting left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

【PRD / 用户文档需要更新】

现有 README 和 Quick Start 只说 “Git repository URL must be accessible from container”,例如 README.md:182、README.zh-CN.md:166、docs/
quickstart.md:92、docs/quickstart.zh-CN.md:90。

PR #62 改成了更明确的产品行为:只接受仓库根地址或 clone URL;拒绝 issues/pull/tree/blob 页面 URL、http/file/ext:: 等不安全协议、带凭据/query/
fragment 的 URL、本地/内网地址。用户文档应该补充这些规则和示例,否则用户仍会以为只要“容器能访问”就行。

另外,当前代码允许 git_repo_url 为空,并且 update 时允许清空;如果这是有意设计,文档也应该说明“仓库地址可暂不填写,但轮询/任务检测会受限”。如
果产品上要求创建项目必须填仓库地址,那 PR 里的实现还需要收紧。(这个应该不能为空?)

【 Tech Spec / 架构文档需要更新】

docs/architecture.md:186 的“关键行为约束”目前没有 Git URL 校验规则,只写了路径安全。建议新增一条“项目 Git 仓库地址校验”:

  • 前后端都有校验,后端是最终防线。
  • 支持 https://host/org/repo(.git)、ssh://user@host/org/repo.git、git@host:org/repo.git。
  • 对 GitHub/GitLab/Bitbucket/Codeberg/Gitee 这类已知 Web Git host,允许不带 .git 的仓库根地址。
  • 对未知 host,要求 repo path 以 .git 结尾。
  • 拒绝页面 URL、query/fragment、凭据、私有/本地/metadata IP、危险协议和 leading dash。
  • 这是格式和安全校验,不是仓库存在性校验。

最后一点很重要:PR 描述里写了“verifies repository accessibility with non-interactive git ls-remote”,但 PR 测试里明确有
test_create_project_accepts_valid_but_unverified_repo_url,也就是 合法格式但不存在/未验证的仓库仍可创建。所以文档不要写“创建时验证仓库存在或可
访问”;如果 PRD 真要求这一点,那代码和测试需要改。

@beautyarbutin
Copy link
Copy Markdown
Contributor Author

【PRD / 用户文档需要更新】

现有 README 和 Quick Start 只说 “Git repository URL must be accessible from container”,例如 README.md:182、README.zh-CN.md:166、docs/ quickstart.md:92、docs/quickstart.zh-CN.md:90。

PR #62 改成了更明确的产品行为:只接受仓库根地址或 clone URL;拒绝 issues/pull/tree/blob 页面 URL、http/file/ext:: 等不安全协议、带凭据/query/ fragment 的 URL、本地/内网地址。用户文档应该补充这些规则和示例,否则用户仍会以为只要“容器能访问”就行。

另外,当前代码允许 git_repo_url 为空,并且 update 时允许清空;如果这是有意设计,文档也应该说明“仓库地址可暂不填写,但轮询/任务检测会受限”。如 果产品上要求创建项目必须填仓库地址,那 PR 里的实现还需要收紧。(这个应该不能为空?)

【 Tech Spec / 架构文档需要更新】

docs/architecture.md:186 的“关键行为约束”目前没有 Git URL 校验规则,只写了路径安全。建议新增一条“项目 Git 仓库地址校验”:

  • 前后端都有校验,后端是最终防线。
  • 支持 https://host/org/repo(.git)、ssh://user@host/org/repo.git、git@host:org/repo.git。
  • 对 GitHub/GitLab/Bitbucket/Codeberg/Gitee 这类已知 Web Git host,允许不带 .git 的仓库根地址。
  • 对未知 host,要求 repo path 以 .git 结尾。
  • 拒绝页面 URL、query/fragment、凭据、私有/本地/metadata IP、危险协议和 leading dash。
  • 这是格式和安全校验,不是仓库存在性校验。

最后一点很重要:PR 描述里写了“verifies repository accessibility with non-interactive git ls-remote”,但 PR 测试里明确有 test_create_project_accepts_valid_but_unverified_repo_url,也就是 合法格式但不存在/未验证的仓库仍可创建。所以文档不要写“创建时验证仓库存在或可 访问”;如果 PRD 真要求这一点,那代码和测试需要改。

此改动允许仓库地址为空,经测试发现轮询时只能被动等待超时。这一项应该收紧,要求创建项目/修改项目时仓库地址必须填写。

@beautyarbutin
Copy link
Copy Markdown
Contributor Author

已根据 review 调整:

  1. 补充了用户文档:

    • README.md
    • README.zh-CN.md
    • docs/quickstart.md
    • docs/quickstart.zh-CN.md

    文档现在说明仓库地址必须填写仓库根地址或 clone URL,并列出允许和拒绝的 URL 类型。

  2. 补充了架构文档:

    • docs/architecture.md

    增加“项目 Git 仓库地址校验”约束,说明前端校验、后端兜底、支持的 URL 形式、已知 Git host 规则、未知 host .git 要求,以及拒绝页面 URL、query/fragment、凭据、本地/内网地址、危险协议等规则。

  3. 收紧了 git_repo_url 为空的行为:

    • 新建项目时仓库地址不能为空;
    • 编辑项目时不允许清空仓库地址;
    • 后端 API 也会拒绝空值,避免绕过前端。
  4. 明确保持“保存时不验证仓库存在性”:

    • 创建/编辑时只做 URL 格式和安全校验;
    • 不执行 git ls-remote;
    • 合法格式但不存在或无权限访问的仓库,会在后续轮询 / git clone 阶段报错。
  5. 优化了轮询阶段 Git 仓库不可访问时的用户提示:

    • 不再向前端展示 git clone 命令、exit code、容器路径等技术细节;
    • 改为提示用户检查仓库是否存在、地址是否正确、是否有访问权限;
    • 原始 git 错误仍保留在后端日志中。

@beautyarbutin
Copy link
Copy Markdown
Contributor Author

70246959f4348734e98cb1fee299188b 创建项目/修改项目时,要求git仓库地址不能为空。

@beautyarbutin
Copy link
Copy Markdown
Contributor Author

已根据两轮 review 意见继续收敛,主要修改如下:

  • 移除了保存项目时的远端可达性 hard reject,创建/编辑项目时只做 URL 格式与安全校验,不再用 git ls-remote 阻塞保存流程。
  • 明确 git_repo_url 为创建和编辑必填;新建项目不能为空,编辑项目时不允许清空。
  • 后端作为最终防线,前端做即时提示;后端错误提示改为面向用户的中文文案。
  • 拒绝仓库内页面或非仓库根路径,例如 issuespulltreeblobgraphs,以及 https://github.com/org/repo/graphs/contributorshttps://github.com/org/repo/foo
  • 对 GitHub/Gitee/Bitbucket/Codeberg 收紧规则:不带 .git 的仓库根地址只接受 owner/repo 两段。
  • 保留 GitLab subgroup 根地址支持,例如 https://gitlab.com/group/subgroup/repo
  • 拒绝 httpfile://ext::、leading dash、query/fragment、URL 内嵌凭据/token。
  • 补充拒绝 localhost、内网、link-local、metadata、非标准私网 IP 写法和 IPv4-mapped private address,例如 127.121307064330x7f000001::ffff:127.0.0.1
  • 修复前端 IPv6 ULA 判断误拒 fcc.comfdic.govgit.fcompany.com 这类合法域名的问题。
  • 更新 README、README.zh-CN、Quick Start 中英文和 architecture 文档,说明合法 URL 形态、拒绝规则、私有仓库凭据建议,以及保存时不验证仓库存在性。
  • 将 Git 同步/轮询失败提示改为更清楚的用户提示:仓库不存在、地址错误或无权限时,后续轮询会提示无法访问 Git 仓库并自动重试。
  • 补充后端、API 层和前端测试,覆盖空 URL、非法 URL、非标准 IP、userinfo/token、GitLab subgroup、GitHub/Gitee 非根路径等场景。

@keting keting self-requested a review May 2, 2026 13:23
@keting keting merged commit 961275c into keting:main May 2, 2026
5 checks passed
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.

[项目管理] Git 仓库地址有效性校验与错误提示

2 participants