Skip to content

Feat/code review app - #1

Closed
Rhosmarie wants to merge 22 commits into
mainfrom
feat/code-review-app
Closed

Feat/code review app#1
Rhosmarie wants to merge 22 commits into
mainfrom
feat/code-review-app

Conversation

@Rhosmarie

Copy link
Copy Markdown
Owner

No description provided.

@Rhosmarie Rhosmarie closed this Sep 7, 2026
@Rhosmarie Rhosmarie reopened this Sep 7, 2026

@agentkit-veadk-studio agentkit-veadk-studio Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Findings

  • [Major] veadk/cli/frontend_sandbox.py_schedule_github_pull_request_review_message 通过 asyncio.create_task() 创建后台任务,但未持有 task 引用。如果事件循环在服务器关闭时终止,可能出现 "Task was destroyed but it is pending" 警告。建议存储 task 引用,并在服务器关闭时优雅地取消它。

  • [Major] veadk/cli/frontend_sandbox.py_schedule_github_pull_request_review_message 中的 _run_review_message 只捕获了 SandboxError,但 stream_message 可能抛出其他异常(如 asyncio.CancelledError 之外的未预期异常),这些异常会被 asyncio 静默吞掉。建议加一个更宽泛的 except 兜底并记录日志。

  • [Minor] veadk/cli/frontend_sandbox.py — PR 评审提示词模板 _GITHUB_PULL_REQUEST_REVIEW_PROMPT 硬编码在代码中(含中文要求)。建议提取到配置文件或常量模块,便于后续维护和国际化。

  • [Minor] frontend/src/automations/pullRequestReview.tssubmit() 函数现在直接抛出错误 "PR 自动评审已切换为 GitHub App 授权模式。" 这意味着旧的 workflow 生成流程被完全移除,已配置该自动化 workflow 的用户需要迁移。建议在 UI 中向用户展示迁移指引。

  • [Minor] veadk/cli/github_app_pr_review.py_app_jwt() 中的 iat 硬编码为 time.time() - 60,这虽然是常见的时钟偏差补偿,但 GitHub 官方推荐 iat 不超过当前时间 60 秒。建议将补偿值提取为常量(如 JWT_IAT_OFFSET),并添加注释说明用途。

  • [Minor] veadk/cli/frontend_sandbox.py — 移除了 _agent_surface_capability_valid_agent_surface_capability 函数,但 SandboxAgentSessionServiceresolve_surface_proxy_target 方法也被简化为 resolve_proxy_target。如果外部有依赖这些能力签名的组件,存在兼容性风险。建议在 PR 描述或提交信息中记录此变更的动机。

  • [Nit] veadk/tools/skills_tools/session_path.py_get_base_path() 中 Linux/macOS 的默认路径硬编码为 /home/gem/veadk_skills/sessions。建议确认该路径是否在目标部署环境中可写,或者考虑使用 $HOME 环境变量。

Open Questions

  • veadk/cli/frontend_sandbox.py 中新增的 TosGitHubAppReviewRepositoryStore 依赖 TOS 对象存储,但 _github_app_review_store() 在没有配置 bucket 时返回 None,此时 webhook 端点会返回 ignored 状态。这是否需要在部署文档中明确说明?
  • 删除了 VeStackManagedTool 相关的 managed tool 系统(包括 create_managed_toollist_managed_toolsdelete_managed_tool 等),这些是否已完全不再使用?如果还有外部依赖,需要确保兼容。

Verification

  • Reviewed PR: #1
  • Reviewed head SHA: d800784f96c604384dbfd96d0af57345baeb18fa
  • 审查了 veadk/cli/github_app_pr_review.py(新建,507 行)、veadk/cli/frontend_sandbox.py(+418/-585)、veadk/tools/builtin_tools/remote_skills.py(+58/-3)、veadk/tools/skills_tools/session_path.py(+13/-8)、frontend/src/adk/githubIntegration.ts(+178/-1)、frontend/src/automations/pullRequestReview.ts(+10/-235)、frontend/src/automations/githubFields.ts(+0/-1)、frontend/src/automations/types.ts(+0/-2)、veadk/tools/skills_tools/bash_tool.py(+2/-2)、veadk/tools/skills_tools/file_tool.py(+3/-3)、pyproject.toml(+1)、tests/tools/test_skills_session_path.py(新建)、tests/tools/builtin_tools/test_remote_skills.py(+96/-6)等关键源文件。
  • 未审查的变更:前端构建产物(veadk/webui/assets/ 下的大量重命名 JS/CSS 文件)、设计图(data/design-lark-chart/ 下的 .jpg 文件)、reference/actb-mono 符号链接、uv.lock 依赖锁定文件,以及 tests/cli/test_frontend_sandbox.py 等大型测试文件。这些文件要么是二进制/构建产物,要么因篇幅过长未逐行检查。
  • CI 状态:之前的 CI 运行中 License-Check 和 test (3.10) 曾失败,但最新的 CI 正在运行中(pre-commit、test、License-Check、gitleaks、gate 等均在 IN_PROGRESS)。
  • 已使用 gh pr viewgh api 获取 PR 元数据和文件列表。
  • 未直接克隆仓库,使用 GitHub API 获取文件内容进行审查。

@agentkit-veadk-studio agentkit-veadk-studio Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Findings

Critical

  1. 权限绕过:手动PR评审端点无仓库访问控制

    • 位置:veadk/cli/frontend_sandbox.py:3809-3845
    • 问题:/web/github/pull-request-reviews端点允许任何认证用户为任意PR创建评审会话,但没有像webhook端点那样检查该仓库是否在管理员启用的评审列表中,也没有验证当前用户是否有权限访问该仓库。攻击者可以利用此端点为GitHub App安装下的任意仓库生成installation token。
    • 影响:横向越权,非授权用户可以访问任意仓库的token并通过沙箱执行操作。
    • 修复:在手动创建评审会话前,必须验证:(1) 目标仓库在管理员启用的评审列表中;(2) 当前用户对该仓库有访问权限。
  2. GitHub token权限过大且直接暴露给沙箱

    • 位置:veadk/cli/frontend_sandbox.py:3605
    • 问题:GitHub App installation token被直接通过GITHUB_TOKEN环境变量注入到沙箱中,agent可以直接使用该token执行任意GitHub API操作。prompt中的"不要修改仓库"只是对LLM的软约束,没有技术层面的强制限制。
    • 影响:token默认拥有GitHub App配置的全部权限(可能包括代码写入、PR合并、Issue修改等),LLM幻觉或prompt注入可能导致仓库被意外修改或恶意操作。
    • 修复:(1) 在生成installation token时,通过permissions参数将token限制为只读权限 + PR评论写入权限;(2) 不要直接暴露原始token,而是通过一个代理层封装仅评审所需的API操作。

Major

  1. 硬编码开发者个人主目录路径
    • 位置:veadk/tools/skills_tools/session_path.py:25
    • 问题:DEFAULT_SKILLS_WORK_DIR被硬编码为/home/gem/veadk_skills/sessions,这是开发者个人的主目录路径,在其他环境(生产环境、其他开发者机器)中会导致路径不存在或权限错误。
    • 影响:会话目录创建失败,功能不可用。
    • 修复:使用跨平台的合理默认路径,如~/.cache/veadk/sessions或使用tempfile.gettempdir()下的目录,与原逻辑保持一致。

Minor

  1. 新增测试文件tests/tools/test_skills_session_path.py缺少Apache License头,这是CI中License-Check失败的直接原因。

  2. 空目录reference/actb-mono被意外提交到仓库,没有任何内容,建议添加.gitkeep或移除。

  3. Webhook触发的自动评审没有速率限制,恶意用户可以通过频繁提交PR创建大量沙箱会话导致资源耗尽。

CI Status

  • License-Check: FAILURE - 主要是新增文件缺少license头
  • Unit Tests (3.10/3.12): FAILURE - 建议在合并前修复测试失败
  • gitleaks/pre-commit: SUCCESS

Verification

  • 评审commit: d800784
  • 检查了所有Python和TypeScript源文件变更
  • 验证了webhook签名验证逻辑正确
  • 未运行本地测试,仅静态代码审查

if match is None:
raise SandboxValidationError("请输入完整的 GitHub Pull Request URL。")
owner, repo, _number = match.groups()
installation_token = await _github_app_installation_token_for_pull_request(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Critical] 此处直接为用户提供的PR URL生成installation token,但没有检查该仓库是否在管理员启用的评审仓库列表中,也没有验证用户是否有权限访问该仓库。任何登录用户都可以使用此接口为GitHub App安装下的任意仓库获取token,造成横向越权。请参考webhook处理逻辑(3768-3780行)加入相同的仓库启用检查,并增加用户权限校验。

creator_name,
False,
envs={
"GITHUB_TOKEN": installation_token,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Critical] GitHub App installation token被直接注入到沙箱环境变量中,沙箱内的所有进程(包括agent执行的任意命令)都可以读取并使用这个token。Prompt中的"不要修改仓库"只是对LLM的软约束,无法防止LLM被prompt注入或产生幻觉时执行写操作。建议:1) 生成token时通过permissions参数限制为只读+PR评论权限;2) 通过服务端代理封装评审所需的API,不直接暴露原始token给沙箱。


# Cache of initialized session paths to avoid re-creating symlinks
_session_path_cache: dict[str, Path] = {}
DEFAULT_SKILLS_WORK_DIR = Path("/home/gem/veadk_skills/sessions")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Major] 此处硬编码了/home/gem/veadk_skills/sessions作为默认路径,这是开发者个人主目录,在生产环境或其他机器上会导致路径不存在或权限错误。建议使用更通用的默认路径,如Path.home()/'.cache'/'veadk'/'sessions',或者恢复原来的/tmp/veadk默认路径。

@@ -0,0 +1,28 @@
from pathlib import Path

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Minor] 此文件缺少Apache License头,这是CI中License-Check检查失败的原因之一。请参考其他Python文件添加标准的Apache 2.0许可证头。

@agentkit-veadk-studio agentkit-veadk-studio Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review Findings (HEAD: f65a3cd)

This review covers the latest commit f65a3cd, including fixes from the previous review round.


Critical

1. 权限绕过:手动PR评审端点仍缺少仓库访问控制检查

  • 位置: veadk/cli/frontend_sandbox.py:4013-4058 (_start_github_pull_request_review)
  • 问题: 对比 webhook 端点(第3930-3946行)会验证 event.repository 是否在管理员启用的评审仓库白名单中,但手动评审端点完全没有此检查。任何已认证用户(不只是管理员)都可以通过传入任意公开/私有仓库的PR URL,为GitHub App安装下的任意仓库获取installation token并创建沙箱会话。
  • 影响: 横向越权 - 攻击者可以访问未授权的私有仓库代码、在沙箱中执行任意操作,甚至通过token修改仓库内容。
  • 修复: 在第4029行获取token之前,必须:
    1. 检查当前用户是否为管理员(或添加明确的RBAC权限控制)
    2. 验证目标仓库 {owner}/{repo} 是否通过 store.enabled_repositories() 在白名单中
    3. 如果store未配置或仓库未启用,返回403错误

2. GitHub Installation Token 权限仍未受限,直接暴露给沙箱

  • 位置: veadk/cli/github_app_pr_review.py:340-349 (installation_token 方法) + frontend_sandbox.py:3663
  • 问题: 调用 /app/installations/{installation_id}/access_tokens 时未传递 permissions 参数,token默认拥有GitHub App配置的全部权限。token被直接通过GITHUB_TOKEN环境变量注入沙箱,prompt中的"不要修改仓库"只是LLM软约束,没有技术强制力。
  • 影响: LLM幻觉、prompt注入或恶意利用都可能导致仓库代码被修改、PR被合并、issue被删除等破坏性操作。
  • 修复:
    1. installation_token() 请求body中添加最小权限原则的permissions
      • pull_requests: read + pull_requests: write(仅用于提交评审评论)
      • contents: read(读取代码)
      • metadata: read
    2. 考虑不要直接暴露原始token,而是封装一个代理层只暴露评审所需的API

Major

3. 硬编码开发者个人主目录路径仍未修复

  • 位置: veadk/tools/skills_tools/session_path.py:23
  • 问题: DEFAULT_SKILLS_WORK_DIR = Path("/home/gem/veadk_skills/sessions") 仍然存在。/home/gem是开发者个人目录,在生产环境或其他开发者机器上不存在,会导致目录创建失败或权限错误。
  • 影响: 会话路径初始化失败,skills工具无法正常工作。
  • 修复: Linux/macOS默认路径应使用 Path.home() / ".cache" / "veadk" / "sessions"Path(tempfile.gettempdir()) / "veadk-sessions",Windows保持现有逻辑即可。

4. 新增测试文件仍然缺少Apache License头

  • 位置: tests/tools/test_skills_session_path.py
  • 问题: 文件开头直接是from pathlib import Path,没有标准的Apache 2.0 License头。CI的License-Check检查会因此失败。
  • 修复: 添加与其他测试文件一致的License头。

Minor

5. 后台任务没有引用持有且异常捕获不完整

  • 位置: veadk/cli/frontend_sandbox.py:3738
  • 问题: asyncio.create_task(_run_review_message()) 创建的后台任务没有保存引用,服务器关闭时可能出现"Task was destroyed but it is pending"警告。另外_run_review_message只捕获了SandboxError,其他异常(如网络错误、JSON解析错误)会被asyncio静默吞掉。
  • 修复: 存储task引用到一个set中,在app shutdown时优雅取消;添加宽泛的except Exception兜底并记录error日志。

6. Webhook自动评审没有速率限制

  • 问题: 恶意用户可以通过频繁创建/更新PR触发大量评审任务,耗尽沙箱资源。
  • 修复: 添加基于installation_id+repository的速率限制(如每仓库每5分钟最多1个并发评审)。

7. JWT iat偏移量建议提取为常量

  • 位置: veadk/cli/github_app_pr_review.py:520
  • 问题: issued_at = int(time.time()) - 60 硬编码60秒时钟偏差补偿,建议提取为常量JWT_CLOCK_SKEW_SECONDS = 60并添加注释。

已修复验证

  • ✅ Pagination UI: 最新提交修复了GitHub设置页面分页按钮在无相邻页面时的隐藏问题
  • ✅ PR Review表单label: 已移除不必要的输入标签
  • ✅ 评审设置加载错误: 仓库列表未加载前避免设置错误提示

Open Questions

  • 删除的VeStackManagedTool系统是否确认无外部依赖?
  • reference/actb-mono空目录是否应该移除或添加.gitkeep?

Verification

  • Reviewed PR: #1
  • Reviewed head SHA: f65a3cd0572068c5406bd982b8c31493f8afff72
  • Diff since previous review (d800784f65a3cd): +1129/-331 lines across source/test files
  • Files examined: veadk/cli/github_app_pr_review.py, veadk/cli/frontend_sandbox.py, veadk/cli/cli_frontend.py, veadk/tools/skills_tools/session_path.py, tests/tools/test_skills_session_path.py
  • CI Status: All checks IN_PROGRESS at review time
  • Note: Frontend build assets and mermaid diagram chunks not reviewed (binary/generated files)

@agentkit-veadk-studio agentkit-veadk-studio Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review Findings (HEAD: 6f1a669)

本评审针对最新提交 6f1a669,覆盖前三轮评审后剩余的问题。前三轮指出的所有 Critical 和 Major 问题均未修复,最新提交仅修改了前端 UI(完成后隐藏会话操作按钮)。


Critical

1. 权限绕过:手动PR评审端点仍缺少仓库访问控制检查(未修复)

  • 位置: veadk/cli/frontend_sandbox.py:4013-4070 (_start_github_pull_request_review)
  • 问题: 对比 webhook 端点(第3924-3946行)会验证 event.repository 是否在管理员启用的评审仓库白名单中,但手动评审端点完全没有此检查。任何已认证用户都可以通过传入任意 PR URL,为 GitHub App 安装下的任意仓库获取 installation token 并创建沙箱会话。
  • 影响: 横向越权 - 攻击者可以访问未授权的私有仓库代码、在沙箱中执行任意操作,甚至通过 token 修改仓库内容。
  • 修复: 在获取 token 之前必须添加与 webhook 一致的检查:
    1. 验证目标仓库 {owner}/{repo} 是否通过 store.enabled_repositories() 在白名单中
    2. 如果 store 未配置或仓库未启用,返回 403 错误

2. GitHub Installation Token 权限仍未受限,直接暴露给沙箱(未修复)

  • 位置: veadk/cli/github_app_pr_review.py:615-627 (installation_token 方法)
  • 问题: 调用 /app/installations/{installation_id}/access_tokens 时未传递 permissions 参数,token 默认拥有 GitHub App 配置的全部权限。token 被直接通过 GITHUB_TOKEN 环境变量注入沙箱,prompt 中的"不要修改仓库"只是 LLM 软约束,没有技术强制力。
  • 影响: LLM 幻觉、prompt 注入或恶意利用都可能导致仓库代码被修改、PR 被合并、issue 被删除等破坏性操作。
  • 修复:
    1. installation_token() 请求 body 中添加最小权限原则的 permissions
      • pull_requests: read + pull_requests: write(仅用于提交评审评论)
      • contents: read(读取代码)
      • metadata: read
    2. 建议不要直接暴露原始 token,而是封装一个代理层只暴露评审所需的 API

Major

3. 硬编码开发者个人主目录路径(未修复)

  • 位置: veadk/tools/skills_tools/session_path.py:23
  • 问题: DEFAULT_SKILLS_WORK_DIR = Path("/home/gem/veadk_skills/sessions") 仍然存在。/home/gem 是开发者个人目录,在生产环境或其他开发者机器上不存在,会导致目录创建失败或权限错误。
  • 影响: 会话路径初始化失败,skills 工具无法正常工作。
  • 修复: Linux/macOS 默认路径应使用 Path.home() / ".cache" / "veadk" / "sessions"Path(tempfile.gettempdir()) / "veadk-sessions"

4. 新增测试文件仍然缺少 Apache License 头(未修复,CI 失败直接原因)

  • 位置: tests/tools/test_skills_session_path.py
  • 问题: 文件开头直接是 from pathlib import Path,没有标准的 Apache 2.0 License 头。这是 CI 中 License-Check FAILURE 的直接原因。
  • 修复: 添加与其他测试文件一致的 License 头(参考其他测试文件开头的版权声明)。

Minor

5. 后台任务没有引用持有且异常捕获不完整(未修复)

  • 位置: veadk/cli/frontend_sandbox.py:3742
  • 问题: asyncio.create_task(_run_review_message()) 创建的后台任务没有保存引用,服务器关闭时可能出现"Task was destroyed but it is pending"警告。另外 _run_review_message 只捕获了 SandboxError,其他异常(如网络错误、JSON 解析错误)会被 asyncio 静默吞掉。
  • 修复: 存储 task 引用到一个集合中,在 app shutdown 时优雅取消;添加宽泛的 except Exception 兜底并记录 error 日志。

6. Webhook 自动评审没有速率限制(未修复)

  • 问题: 恶意用户可以通过频繁创建/更新 PR 触发大量评审任务,耗尽沙箱资源。
  • 修复: 添加基于 installation_id + repository 的速率限制(如每仓库每 5 分钟最多 1 个并发评审)。

7. JWT iat 偏移量建议提取为常量(未修复)

  • 位置: veadk/cli/github_app_pr_review.py:739
  • 问题: issued_at = int(time.time()) - 60 硬编码 60 秒时钟偏差补偿,建议提取为常量 JWT_CLOCK_SKEW_SECONDS = 60 并添加注释说明用途。

CI Status

  • License-Check: FAILURE - 主要原因是新增测试文件缺少 license 头
  • build: FAILURE - 需要检查构建日志
  • pre-commit/gitleaks/codex-smoke/gate: SUCCESS
  • test (3.10/3.12): PENDING

Verification

  • Reviewed PR: #1
  • Reviewed head SHA: 6f1a6690ab3765769c20ceb93ef772eed08a643c
  • Diff since previous review (f65a3cd6f1a669): 仅前端 UI 变更(评审完成后隐藏会话操作按钮),核心后端安全问题均未修复
  • Files examined: veadk/cli/github_app_pr_review.py, veadk/cli/frontend_sandbox.py, veadk/tools/skills_tools/session_path.py, tests/tools/test_skills_session_path.py
  • Note: 前端构建产物、mermaid diagram chunks、设计图片未审查(二进制/生成文件)

@agentkit-veadk-studio agentkit-veadk-studio Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review Findings (HEAD: dcf3ee7)

本评审针对最新提交 dcf3ee7("delete useless file",仅删除了 4 个设计图 JPG 文件)。前四轮评审指出的所有 Critical 和 Major 问题均未修复,且本轮发现一个新的 CI 构建阻塞问题(gitlink 损坏)。


Critical

1. [Critical] 权限绕过:手动PR评审端点仍缺少仓库访问控制检查(未修复,第五轮)

  • 位置:veadk/cli/frontend_sandbox.py:4029(见内联评论)
  • Webhook 端点(第3924行)正确验证了 enabled_repositories() 白名单,但手动评审端点完全跳过此检查,且无管理员权限校验。任何已认证用户可通过传入任意 PR URL 获取 GitHub App installation token 并创建沙箱会话。

2. [Critical] GitHub Installation Token 权限仍未受限,原始 token 直接暴露给沙箱(未修复,第五轮)

  • 位置:veadk/cli/github_app_pr_review.py:617veadk/cli/frontend_sandbox.py:3663(见内联评论)
  • 获取 token 时未传递 permissions 参数,token 继承 App 全部权限;原始 token 通过 GITHUB_TOKEN 环境变量直接注入沙箱,prompt 中的"不要修改仓库"只是 LLM 软约束。

Major

3. [Major] 新增 gitlink 导致 CI build 失败(新发现)

  • reference/actb-mono 以 gitlink(mode 160000,指向 commit 7d6536a8)方式被提交,但仓库中没有 .gitmodules 文件。CI checkout 阶段执行 git submodule foreach 时报错 fatal: No url found for submodule path 'reference/actb-mono' in .gitmodules,导致 build job 直接失败。
  • 修复:删除该 gitlink 条目(git rm --cached reference/actb-mono),若需保留空目录请添加 .gitkeep;若确实需要子模块,请补全 .gitmodules 配置。

4. [Major] 硬编码开发者个人主目录路径(未修复,第五轮)

  • 位置:veadk/tools/skills_tools/session_path.py:23(见内联评论)
  • DEFAULT_SKILLS_WORK_DIR = Path("/home/gem/veadk_skills/sessions") 在非开发者环境中不存在,将导致目录创建失败。

5. [Major] 新增测试文件缺少 Apache License 头导致 License-Check 失败(未修复,第五轮)

  • 位置:tests/tools/test_skills_session_path.py:1(见内联评论)
  • CI 明确报告该文件缺少 license header(1006 文件中唯一无效的文件)。

Minor

6. 后台任务 asyncio.create_task(_run_review_message())(第3742行)未持有引用,服务器关闭时可能出现 "Task was destroyed but it is pending" 警告;且 _run_review_message 仅捕获 SandboxError,其他异常会被 asyncio 静默吞掉。建议保存 task 引用到集合中,shutdown 时优雅取消,并添加 except Exception 兜底记录 error 日志。(见内联评论)

7. Webhook 自动评审无速率限制,恶意用户可通过频繁创建/更新 PR 耗尽沙箱资源。建议添加基于 installation_id + repository 的并发/频率限制。

8. JWT iat 偏移量硬编码为 time.time() - 60github_app_pr_review.py:739),建议提取为常量 JWT_CLOCK_SKEW_SECONDS = 60 并添加注释。


CI Status

  • License-Check: FAILUREtests/tools/test_skills_session_path.py 缺少 license header
  • build: FAILUREreference/actb-mono gitlink 无 .gitmodules 配置导致 submodule 错误
  • pre-commit: PASS | harness-sidecar-release-gate/gate: PASS
  • test (3.10/3.12): 未运行(build 失败前置阻塞)
  • Merge status: CONFLICTING(与 main 分支存在合并冲突)

Verification

  • Reviewed PR: #1
  • Reviewed head SHA: dcf3ee734b561502b5ea6d14192b891011aaaa9a
  • Diff since previous review (6f1a669dcf3ee7): 仅删除 4 个设计图 JPG 文件(data/design-lark-chart/review-poc-sync/*.jpg),核心后端安全/正确性问题均未修复
  • 通过 gh repo clone + git fetch pull/1/head 获取完整代码进行逐文件审查
  • 已检查 CI 失败日志(build 和 License-Check)
  • 前端构建产物(veadk/webui/assets/)、uv.lock 未逐行审查(生成的/锁定文件)

if match is None:
raise SandboxValidationError("请输入完整的 GitHub Pull Request URL。")
owner, repo, _number = match.groups()
installation_token = await _github_app_installation_token_for_pull_request(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Critical] 此处直接调用 _github_app_installation_token_for_pull_request(owner, repo) 获取 installation token,没有像 webhook 端点(第3924-3946行)那样验证 {owner}/{repo} 是否在 store.enabled_repositories() 白名单中,也没有校验当前用户是否为管理员。

影响:横向越权。任何已认证用户可传入任意仓库(包括私有仓库)的 PR URL,获取该仓库的 installation token 并在沙箱中执行操作,包括读取/修改代码。

修复:在获取 token 之前,必须添加与 webhook 一致的检查:

  1. 检查 store 是否可用;
  2. 验证 f"{owner}/{repo}".casefold() 是否在启用仓库集合中;
  3. 建议同时校验 _is_admin(request) 或添加明确的 RBAC 权限控制;
  4. 不在白名单中返回 403。

self._timeout = timeout

async def installation_token(self, installation_id: int) -> str:
payload = await self._request(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Critical] 调用 /app/installations/{installation_id}/access_tokens 时未在请求 body 中传递 permissions 参数,生成的 token 将继承 GitHub App 配置的全部权限(可能包括 contents:write、pull_requests:write、issues:write 等)。

结合 frontend_sandbox.py:3663 将此 token 直接作为 GITHUB_TOKEN 环境变量注入沙箱,且仅靠 prompt 中的约束来限制 LLM 行为,无法在技术层面阻止 token 被用于破坏性操作(合并 PR、推送代码、删除 issue 等)。

修复建议

  1. 在 POST body 中添加最小权限 permissions:仅需 contents: readmetadata: readpull_requests: read + pull_requests: write(评论需要写权限);
  2. 考虑不直接暴露原始 token,而是在后端封装一个仅暴露评审所需 API(读 PR、提交评论)的代理层。

@@ -21,6 +22,16 @@

# Cache of initialized session paths to avoid re-creating symlinks

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Major] DEFAULT_SKILLS_WORK_DIR 硬编码为 /home/gem/veadk_skills/sessions,这是开发者个人主目录路径。在生产部署、其他开发者机器或 CI 环境中,该路径要么不存在,要么当前用户无写入权限,将导致会话目录创建失败、skills 工具不可用。

对应的测试用例(tests/tools/test_skills_session_path.py:9)也断言了这个硬编码路径,进一步固化了问题。

修复:Linux/macOS 默认路径应使用 Path.home() / ".cache" / "veadk" / "sessions"Path(tempfile.gettempdir()) / "veadk-sessions",与 Windows 分支逻辑保持一致。

@@ -0,0 +1,28 @@
from pathlib import Path

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Major] 文件缺少 Apache License 2.0 版权头。CI License-Check(skywalking-eyes/header)明确报告该文件为 1006 个被检查文件中唯一缺少有效 license header 的文件,直接导致 License-Check job FAILURE。

修复:在文件开头添加与其他测试文件一致的 Apache 2.0 License 头(参考仓库中其他 tests/ 下文件的开头格式)。

_safe_error_message(error),
)

asyncio.create_task(_run_review_message())

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Minor] asyncio.create_task(_run_review_message()) 创建的后台任务没有保存引用。根据 Python asyncio 文档,未持有引用的 Task 可能在任何时候被垃圾回收,导致 "Task was destroyed but it is pending" 警告并中断执行。

此外,_run_review_message(第3725行)只捕获了 SandboxError,其他异常(网络超时、JSON 解析错误、stream_message 内部错误等)会导致 Task 静默失败,评审状态永远停留在 "started"。

修复

  1. 将 task 保存到模块级 set 中防止被 GC,并在 app shutdown 时统一取消;
  2. 添加 except Exception as error 兜底分支,调用 _update_status("failed", ...) 并记录 logger.exception(...)

@agentkit-veadk-studio agentkit-veadk-studio Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review Findings (HEAD: 9630bc0 — 第六轮评审)

本评审针对最新提交 9630bc0(两次合并 origin/main 后的快照)。自上一轮评审(dcf3ee7)以来,两次合并仅带入了 main 分支的改动(managed tool disk storage 能力、前端构建产物重命名等),前五轮指出的所有 Critical 和 Major 问题均未修复


Critical(未修复,第六轮)

1. 权限绕过:手动 PR 评审端点仍缺少仓库访问控制检查

  • 位置:veadk/cli/frontend_sandbox.py:4053(见内联评论)
  • Webhook 端点(第3948行)正确验证了 enabled_repositories() 白名单,但手动评审端点在第4053行直接调用 _github_app_installation_token_for_pull_request(owner, repo) 获取 token 并创建沙箱会话,完全跳过了仓库白名单检查
  • 影响:横向越权,任何已认证用户可传入任意 PR URL 获取 GitHub App installation token 并执行沙箱操作。
  • 修复:在第4053行获取 token 前,添加与 webhook 端点一致的 enabled_repositories() 白名单检查。

2. GitHub Installation Token 权限仍未受限,原始 token 直接暴露给沙箱

  • 位置:veadk/cli/github_app_pr_review.py:615(见内联评论)
  • 获取 token 时未传递 permissions 参数,token 继承 App 全部权限;原始 token 通过 GITHUB_TOKEN 环境变量直接注入沙箱(frontend_sandbox.py:3687),prompt 中的"不要修改仓库"只是 LLM 软约束。
  • 影响:LLM 幻觉或 prompt 注入可能导致仓库代码被修改、PR 被合并等破坏性操作。

Major(未修复,第六轮)

3. Gitlink 导致 CI build 失败

  • 位置:reference/actb-mono(mode 160000,指向 commit 7d6536a8
  • 仓库中没有 .gitmodules 文件,CI checkout 执行 git submodule foreach 时报错 fatal: No url found for submodule path 'reference/actb-mono' in .gitmodules,导致 build 失败。
  • 修复:git rm --cached reference/actb-mono 删除该 gitlink;若需保留空目录请添加 .gitkeep

4. 硬编码开发者个人主目录路径

  • 位置:veadk/tools/skills_tools/session_path.py:25(见内联评论)
  • DEFAULT_SKILLS_WORK_DIR = Path("/home/gem/veadk_skills/sessions") 在非开发者环境不存在。
  • 测试文件 test_skills_session_path.py 甚至断言了这个硬编码路径(第10行),进一步固化了该问题。

5. 新增测试文件缺少 Apache License 头导致 License-Check 失败

  • 位置:tests/tools/test_skills_session_path.py:1(见内联评论)
  • 这是 CI License-Check FAILURE 的直接原因(1006 个文件中唯一无效的文件)。

Minor(未修复,第六轮)

6. 后台任务 asyncio.create_task(_run_review_message())frontend_sandbox.py:3766,见内联评论)未持有引用,服务器关闭时可能出现 "Task was destroyed but it is pending" 警告;且 _run_review_message 仅捕获 SandboxError,其他异常会被 asyncio 静默吞掉。

7. Webhook 自动评审无速率限制,恶意用户可通过频繁创建/更新 PR 耗尽沙箱资源。

8. JWT iat 偏移量硬编码为 time.time() - 60github_app_pr_review.py:739,见内联评论),建议提取为常量 JWT_CLOCK_SKEW_SECONDS = 60 并添加注释。


CI Status

  • License-Check: FAILUREtests/tools/test_skills_session_path.py 缺少 license header
  • gate: FAILURE — build 被 gitlink 问题阻塞
  • pre-commit: PASS | gitleaks: PASS | codex-smoke: PASS
  • test (3.10/3.12): PENDING(gate 失败前置阻塞)

Verification

  • Reviewed PR: #1
  • Reviewed head SHA: 9630bc0d64ff02d6b0395b5370bf3026966d902c
  • Diff since previous review (dcf3ee79630bc0): 两次 origin/main 合并带入的 main 分支变更(managed tool disk storage 能力 + 前端构建产物更新),PR 核心功能文件无新修复
  • 通过 gh repo clone + gh pr checkout 获取完整代码逐文件审查
  • 前端构建产物(veadk/webui/assets/)、uv.lockpackage-lock.json 未逐行审查(生成的/锁定文件)

if match is None:
raise SandboxValidationError("请输入完整的 GitHub Pull Request URL。")
owner, repo, _number = match.groups()
installation_token = await _github_app_installation_token_for_pull_request(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Critical] 此处直接调用 _github_app_installation_token_for_pull_request(owner, repo) 获取 GitHub App installation token,然后在第4058行创建沙箱会话,但没有像 webhook 端点(第3948行)那样检查目标仓库是否在管理员启用的白名单 enabled_repositories()

任何已认证用户都可以传入任意仓库(包括未授权的私有仓库)的 PR URL,获取该仓库的 installation token 并在沙箱中执行操作,构成横向越权漏洞。

修复建议:在此行之前添加与 webhook 端点一致的检查逻辑:

store = _github_app_review_store()
if store is None:
    raise SandboxError("评审设置不可用")
enabled = await store.enabled_repositories()
repo_full = f"{owner}/{repo}"
if repo_full.casefold() not in {r.casefold() for r in enabled}:
    raise SandboxError(f"仓库 {repo_full} 未启用 PR 评审")

self._api_root = api_root.rstrip("/")
self._timeout = timeout

async def installation_token(self, installation_id: int) -> str:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Critical] installation_token() 方法向 /app/installations/{installation_id}/access_tokens 发送 POST 请求时,没有在请求 body 中传递 permissions 参数,因此返回的 token 默认拥有 GitHub App 配置的全部权限(可能包括 contents:write、pull_requests:write、issues:write 等)。

随后此 token 被通过 GITHUB_TOKEN 环境变量直接注入沙箱(frontend_sandbox.py:3687),LLM prompt 中的"不要修改仓库"只是软约束,没有技术强制力。

修复建议:

  1. 在请求 body 中添加最小权限 permissions
    body = {
        "permissions": {
            "contents": "read",
            "pull_requests": "write",
            "metadata": "read"
        }
    }
  2. 考虑不直接暴露原始 token,而是封装代理层只暴露评审所需的 API 操作。


# Cache of initialized session paths to avoid re-creating symlinks
_session_path_cache: dict[str, Path] = {}
DEFAULT_SKILLS_WORK_DIR = Path("/home/gem/veadk_skills/sessions")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Major] DEFAULT_SKILLS_WORK_DIR 被硬编码为 /home/gem/veadk_skills/sessions,这是开发者个人的主目录路径。在生产环境或其他开发者机器上,/home/gem 目录不存在或无写权限,会导致会话目录创建失败、skills 工具不可用。

另外,测试文件 tests/tools/test_skills_session_path.py:10 还断言了这个硬编码路径,进一步固化了该问题。

修复建议:Linux/macOS 默认路径应改为:

DEFAULT_SKILLS_WORK_DIR = Path.home() / ".cache" / "veadk" / "sessions"
# 或使用 tempfile: Path(tempfile.gettempdir()) / "veadk-sessions"

@@ -0,0 +1,28 @@
from pathlib import Path

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Major] 此文件缺少 Apache 2.0 License 头,是 CI License-Check FAILURE 的直接原因(1006 个文件中唯一无效的文件)。

修复:参考项目中其他测试文件,在文件开头添加标准的 Apache 2.0 版权声明头(例如参考 tests/tools/builtin_tools/test_remote_skills.py 的开头)。

_safe_error_message(error),
)

asyncio.create_task(_run_review_message())

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Minor] asyncio.create_task(_run_review_message()) 创建的后台任务没有保存引用。根据 Python asyncio 文档,未持有引用的 Task 可能在执行完成前被垃圾回收,导致 "Task was destroyed but it is pending!" 警告,且任务中的异常(除了已捕获的 SandboxError)会被 asyncio 的 exception handler 静默吞掉。

修复建议:

  1. 将 task 引用存储到一个模块级别的 set() 中防止被 GC;
  2. 添加 except Exception 兜底捕获并记录 error 日志:
_background_tasks: set[asyncio.Task] = set()
task = asyncio.create_task(_run_review_message())
_background_tasks.add(task)
task.add_done_callback(_background_tasks.discard)

raise GitHubAppReviewError(
"缺少 PyJWT 依赖,无法生成 GitHub App JWT。"
) from error
issued_at = int(time.time()) - 60

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Minor] issued_at = int(time.time()) - 60 中的 60 秒时钟偏差补偿值是硬编码的魔法数字。建议提取为常量 JWT_CLOCK_SKEW_SECONDS = 60 并添加注释说明其用途(补偿客户端与 GitHub 服务器之间的时钟偏差)。

@agentkit-veadk-studio agentkit-veadk-studio Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review Findings (HEAD: ff84c73 — 第七轮评审)

本评审针对最新提交 ff84c73("fix(ci): resolve sandbox stream schema and lockfile issues")。自上一轮评审(9630bc0)以来,最新提交修复了测试文件 License 头问题和 sandbox stream schema 兼容性问题,License-Check 和 gate CI 检查已通过。但前六轮指出的 2 个 Critical 安全问题和核心 Major 问题均未修复


✅ 已修复

  • 测试文件缺少 Apache License 头tests/tools/test_skills_session_path.py 已添加标准 License 头,CI License-Check 现已通过
  • Sandbox stream schema 兼容性stream_message 接口添加了缺失的 output_schema 参数

Critical(未修复,第七轮)

1. 权限绕过:手动 PR 评审端点仍缺少仓库访问控制白名单检查

  • 位置:veadk/cli/frontend_sandbox.py:4056(见内联评论)
  • Webhook 端点(第 3951 行)正确验证了 enabled_repositories() 白名单,但手动评审端点在第 4056 行直接调用 _github_app_installation_token_for_pull_request(owner, repo) 获取 token 并创建沙箱会话,完全跳过了仓库白名单检查和管理员权限校验
  • 影响:横向越权 - 任何已认证用户可传入任意 PR URL(包括私有仓库),获取 GitHub App installation token 并在沙箱中执行任意操作。
  • 修复:在第 4056 行获取 token 前,必须添加与 webhook 端点一致的 enabled_repositories() 白名单检查。

2. GitHub Installation Token 权限仍未受限,原始 token 直接暴露给沙箱

  • 位置:veadk/cli/github_app_pr_review.py:617(见内联评论)+ veadk/cli/frontend_sandbox.py:3690
  • 获取 token 时调用 POST /app/installations/{installation_id}/access_tokens 未传递 permissions 参数,token 继承 GitHub App 配置的全部权限;原始 token 通过 GITHUB_TOKEN 环境变量直接注入沙箱,prompt 中的"不要修改仓库"只是 LLM 软约束,没有技术强制力。
  • 影响:LLM 幻觉、prompt 注入或恶意利用都可能导致仓库代码被修改、PR 被合并、issue 被删除等破坏性操作。
  • 修复:(1) 在 access_tokens 请求 body 中添加最小权限 permissions: {"pull_requests": "write", "contents": "read", "metadata": "read"};(2) 考虑封装代理层而不是直接暴露原始 token。

Major(未修复,第七轮)

3. 硬编码开发者个人主目录路径

  • 位置:veadk/tools/skills_tools/session_path.py:25(见内联评论)
  • DEFAULT_SKILLS_WORK_DIR = Path("/home/gem/veadk_skills/sessions") 是开发者个人目录,在生产环境或其他开发者机器上不存在,会导致目录创建失败或权限错误。代码注释中也硬编码了该路径。
  • 影响:Skills 会话路径初始化失败,相关工具不可用。
  • 修复:Linux/macOS 默认路径应使用 Path.home() / ".cache" / "veadk" / "sessions"Path(tempfile.gettempdir()) / "veadk-sessions"

Minor(未修复,第七轮)

4. 后台任务 asyncio.create_task(_run_review_message())frontend_sandbox.py:3769,见内联评论)未持有引用,服务器关闭时可能出现 "Task was destroyed but it is pending" 警告;且 _run_review_message 仅捕获 SandboxError,其他异常会被 asyncio 静默吞掉。参考第 1045-1047 行已有正确的 _background_tasks 管理模式,应保持一致。

5. Webhook 自动评审无速率限制,恶意用户可通过频繁创建/更新 PR 触发大量评审任务,耗尽沙箱资源。

6. JWT iat 偏移量硬编码为 int(time.time()) - 60github_app_pr_review.py:739,见内联评论),建议提取为常量 JWT_CLOCK_SKEW_SECONDS = 60 并添加注释说明用途。


CI Status

  • License-Check: PASS ✅(已修复)
  • pre-commit/gitleaks/codex-smoke/gate: PASS
  • build: FAILURE
  • test (3.10/3.12): PENDING(前置依赖)
  • reference/actb-mono gitlink:仍以 mode 160000 形式存在且无 .gitmodules,但 gate 检查现已通过,不再阻塞合并(仍建议清理)

Verification

  • Reviewed PR: #1
  • Reviewed head SHA: ff84c73d626c0f40cc217cb5e1f5e9da5763fb9e
  • Diff since previous review (9630bc0ff84c73): 4 个文件变更,修复了 License 头和 sandbox stream schema 问题,但核心后端安全问题均未修复
  • 通过 gh repo clone + git fetch pull/1/head 获取完整代码逐文件审查
  • 已检查 CI 最新状态
  • 前端构建产物(veadk/webui/assets/)、uv.lockpackage-lock.json 未逐行审查(生成的/锁定文件)

if match is None:
raise SandboxValidationError("请输入完整的 GitHub Pull Request URL。")
owner, repo, _number = match.groups()
installation_token = await _github_app_installation_token_for_pull_request(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Critical] 在获取 GitHub installation token 前缺少仓库白名单检查。对比 Webhook 端点(第 3951 行)会先验证 store.enabled_repositories() 中是否包含目标仓库,但手动端点此处直接调用 _github_app_installation_token_for_pull_request(owner, repo) 获取 token,任何已认证用户都可以为任意仓库创建评审会话,造成横向越权。必须在此处添加与 webhook 一致的白名单验证逻辑。


async def installation_token(self, installation_id: int) -> str:
payload = await self._request(
"POST",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Critical] 获取 installation token 时未限制权限。调用 POST /app/installations/{installation_id}/access_tokens 时请求体为空,token 将继承 GitHub App 配置的全部权限(可能包括代码写入、PR合并等)。token 随后被直接通过 GITHUB_TOKEN 环境变量注入沙箱(frontend_sandbox.py:3690),prompt 中的"不要修改仓库"只是 LLM 软约束,没有技术强制力。必须在请求 body 中添加最小权限原则的 permissions{"pull_requests": "write", "contents": "read", "metadata": "read"},仅授予评审所需权限。


# Cache of initialized session paths to avoid re-creating symlinks
_session_path_cache: dict[str, Path] = {}
DEFAULT_SKILLS_WORK_DIR = Path("/home/gem/veadk_skills/sessions")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Major] DEFAULT_SKILLS_WORK_DIR = Path("/home/gem/veadk_skills/sessions") 硬编码了开发者个人主目录路径,在生产环境、其他开发者机器或容器环境中该路径不存在,会导致目录创建失败和功能不可用。应使用跨平台默认路径,如 Path.home() / ".cache" / "veadk" / "sessions"Path(tempfile.gettempdir()) / "veadk-sessions"(下方注释也同步硬编码了该路径,需要一并修改)

_safe_error_message(error),
)

asyncio.create_task(_run_review_message())

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Minor] asyncio.create_task(_run_review_message()) 创建的后台任务没有保存引用,服务器关闭时可能出现 "Task was destroyed but it is pending" 警告。另外 _run_review_message 只捕获了 SandboxError,其他异常(网络错误、JSON 解析错误等)会被 asyncio 静默吞掉且不更新 review record 状态。参考第 1045-1047 行的 _background_tasks 模式,保存 task 引用到集合并在 shutdown 时优雅取消;同时添加 except Exception 兜底记录 error 日志并标记 review 状态为 failed。

raise GitHubAppReviewError(
"缺少 PyJWT 依赖,无法生成 GitHub App JWT。"
) from error
issued_at = int(time.time()) - 60

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[Nit] issued_at = int(time.time()) - 60 硬编码 60 秒时钟偏差补偿。建议提取为常量 JWT_CLOCK_SKEW_SECONDS = 60 并添加注释说明这是为了补偿 GitHub App JWT 的时钟偏差问题,提升可维护性。

@agentkit-veadk-studio agentkit-veadk-studio Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review Findings (HEAD: 6a68651 — 第八轮评审)

本评审针对最新提交 6a68651 ("fix(test): remove release entrypoint shutdown race")。该提交仅修复了 tests/cli/test_studio_release.py 中的测试竞态条件。前七轮指出的 2 个 Critical 安全问题和核心 Major 问题仍未修复


✅ 本轮已修复/CI状态

  • 测试竞态条件:tests/cli/test_studio_release.py shutdown race 已修复
  • License-Check: PASS
  • pre-commit/gitleaks/codex-smoke/gate: PASS
  • build/test (3.10/3.12): PENDING

Critical(未修复,第八轮)

1. 权限绕过:手动 PR 评审端点仍缺少仓库访问控制白名单检查

  • 位置:veadk/cli/frontend_sandbox.py:4056-4059 (/web/github/pull-request-reviews POST 端点)
  • 问题:对比 webhook 端点(第 3951-3970 行)正确验证了 enabled_repositories() 白名单,但手动评审端点在第 4056 行直接调用 _github_app_installation_token_for_pull_request(owner, repo) 获取 token 并创建沙箱会话,完全跳过了仓库白名单检查和管理员权限校验
  • 影响:横向越权 — 任何已认证用户可传入任意 PR URL(包括 GitHub App 安装下的私有仓库),获取 installation token 并在沙箱中执行任意代码操作,可读取私有仓库代码。
  • 修复:在第 4056 行获取 token 前,必须添加与 webhook 端点一致的检查:(1) 验证 store is not None;(2) 验证目标仓库在 enabled_repositories() 白名单中;(3) 推荐额外校验当前用户是否为管理员。

2. GitHub Installation Token 权限仍未受限,原始 token 直接暴露给沙箱

  • 位置:veadk/cli/github_app_pr_review.py:614-625 (installation_token 方法) + veadk/cli/frontend_sandbox.py:3690 (通过 GITHUB_TOKEN 环境变量注入沙箱)
  • 问题:调用 POST /app/installations/{installation_id}/access_tokens 时未传递 permissions 参数,token 继承 GitHub App 配置的全部权限;原始 token 通过环境变量直接注入沙箱,prompt 中的软约束没有技术强制力。
  • 影响:LLM 幻觉、prompt 注入或恶意利用都可能导致仓库代码被修改、PR 被合并等破坏性操作。
  • 修复:(1) 在 access_tokens 请求 body 中添加最小权限 permissions: {"pull_requests": "write", "contents": "read", "metadata": "read"};(2) 推荐封装代理层而不是直接暴露原始 token。

Major(未修复,第八轮)

3. 硬编码开发者个人主目录路径

  • 位置:veadk/tools/skills_tools/session_path.py:25
  • 问题:DEFAULT_SKILLS_WORK_DIR = Path("/home/gem/veadk_skills/sessions") 是开发者个人目录,在生产环境或其他机器上不存在。
  • 影响:Skills 会话路径初始化失败,相关工具不可用。
  • 修复:使用 Path.home() / ".cache" / "veadk" / "sessions" 或 tempfile 目录;同步更新测试断言。

Minor(未修复,第八轮)

  1. 后台任务 asyncio.create_task(_run_review_message()) (frontend_sandbox.py:3769) 未使用已有的 _background_tasks 集合管理,异常捕获不完整。
  2. JWT iat 偏移量硬编码为 60 秒 (github_app_pr_review.py:739),建议提取为常量。
  3. Webhook 自动评审无速率限制,存在资源耗尽风险。
  4. reference/actb-mono gitlink 残留(无 .gitmodules),建议清理。

Verification

  • Reviewed PR: #1
  • Reviewed head SHA: 6a68651
  • Diff since previous review (ff84c736a68651): 仅 1 个测试文件 1 行变更,核心安全问题均未修复

@Rhosmarie Rhosmarie closed this Sep 8, 2026
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.

1 participant