Skip to content

fix: 修复远程 Skill 宿主文件读取并隔离拉取流程 - #904

Merged
xerrors merged 8 commits into
xerrors:mainfrom
Yuchuan925:fix/remote-skill-source-allowlist
Aug 12, 2026
Merged

fix: 修复远程 Skill 宿主文件读取并隔离拉取流程#904
xerrors merged 8 commits into
xerrors:mainfrom
Yuchuan925:fix/remote-skill-source-allowlist

Conversation

@Yuchuan925

Copy link
Copy Markdown
Collaborator

变更描述

本 PR 修复远程 Skill 安装链路中的宿主文件读取风险,关联 xerrors/Yuxi#895,并将实现收敛到清晰、可维护的安全边界。

原链路在 API 宿主执行 npx skills。恶意仓库中的符号链接可能被 CLI 解引用,使宿主文件进入 Skill 草稿、安装或导出流程。

当前方案只保留两层必要防护:

  1. 来源治理:管理员配置精确的远程 hostname 白名单。
  2. 执行隔离:远程 Skill 的发现和拉取在无凭据的一次性 Sandbox 中执行;宿主只接收 Sandbox 文件 API 返回的普通 bytes。

设计与实现

精确来源白名单

  • 复用 PostgreSQL config_options,默认允许 github.commodelscope.cn
  • 配置入口位于「设置 → 基本设置 → Skill 配置」。
  • 显式空数组表示关闭远程安装,不回退到默认值。
  • 运行时精确匹配规范化 hostname;要求 HTTPS、443 端口且 URL 不包含凭据、query 或 fragment。
  • GitHub owner/repo 简写仍受 github.com 白名单约束,www.github.com 不再隐式等同于 github.com

白名单负责产品来源治理,不等同于 Sandbox 网络出口防火墙。

一次性无凭据 Sandbox

  • npx skills add --list、批量准备和搜索统一在一次性 Provisioner Sandbox 中执行。
  • inherit_env=False 阻止继承全局 sandbox.env 和用户 Agent 环境变量。
  • Kubernetes Sandbox 禁止自动挂载 ServiceAccount token。
  • Provisioner 不可用时明确失败,不回退到宿主执行。
  • 本地 Sandbox Skill 下载通过工作线程执行,避免阻塞事件循环。

简化后的 Sandbox 回流

  • 先递归枚举并校验目录,再通过现有 download_files() 获取普通 bytes。
  • Sandbox 返回路径必须是请求根目录的词法后代,显式拒绝 ..、根外路径和重复目录。
  • 每个 Skill 最多 1000 个文件、2000 个条目、64 层、声明及实际内容合计 100 MB。
  • 下载失败、实际大小超限或宿主写入失败时,删除本次创建的目标目录;已有目标目录不会被删除。
  • Agent 从当前 Sandbox 安装 Skill 时复用同一目录下载边界。

本轮删除了逐级 openat/O_NOFOLLOW、Sandbox 临时文件、SHA-256 校验、原子限长读取、专用 limited-download 响应和执行位恢复。标准文件 API 返回完整 bytes 后才检查实际总大小,因此这里不再承诺传输前内存硬上限、原子 no-follow 或 TOCTOU 防护。该取舍与当前威胁模型一致:远程代码在无凭据 Sandbox 内运行,宿主只校验返回路径并写入普通 bytes。

影响范围

  • 远程 Skill list / prepare / batch / search。
  • Sandbox 到宿主的 Skill 目录下载。
  • Agent 从当前 Sandbox 安装个人 Skill。
  • 远程来源配置及对应正式文档。

现有 Skill 权限、共享范围、草稿协议、冲突改名和批量结果顺序保持不变。

变更类型

  • 新功能
  • Bug 修复
  • 文档更新
  • 其他

测试

  • 已在 Docker 环境测试
  • 相关功能正常工作
image

自动化验证

  • 相关单元测试:115 passed
  • 真实 API 集成测试:11 passed
  • Ruff check:通过
  • Ruff format check:通过
  • git diff --check:通过
  • 全新上下文独立 Agent Review:通过

覆盖范围包括:

  • 默认、自定义及显式空白名单和精确 hostname 匹配。
  • 远程 list / prepare / batch / search 的 Sandbox 执行与清理。
  • inherit_env=False 在 backend、provider、client、Docker 和 Kubernetes 的传递。
  • Kubernetes ServiceAccount token 禁用。
  • 返回路径越界、文件数、条目数、目录深度、声明及实际总大小限制。
  • 部分下载失败清理和已有目标目录保护。
  • Agent Sandbox 安装、本地下载线程卸载及 300 秒命令/HTTP 超时。

安全边界与非目标

关联与说明

  • 关联:xerrors/Yuxi#895
  • 对比:xerrors/Yuxi#855
  • 贡献者已人工审阅实现与测试结果,明确要求移除过度设计,并接受上述简化后的安全边界。
贡献说明

本 PR 使用 Codex 辅助完成。贡献者已人工审阅全部改动,并完成以下验证:

  • 检查实现与任务范围
  • 检查敏感信息和安全风险
  • 运行相关测试与静态检查

💡 提示:提交前可以运行 make lintmake format 检查代码规范。

@xerrors
xerrors marked this pull request as ready for review August 11, 2026 15:32
Copilot AI lite review requested due to automatic review settings August 11, 2026 15:32

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

该 PR 针对远程 Skill 安装链路(npx skills 在宿主执行导致的 symlink 解引用风险)做安全修复:通过“来源白名单治理 + 一次性无凭据 Sandbox 执行”的方式,将不可信远程仓库的拉取与目录回流隔离到 Sandbox 中,宿主侧只接收并落盘经校验的普通 bytes,从而阻断 #895 描述的宿主文件读取链路。

Changes:

  • 新增并接入 remote_skill_source_policy 配置项(PostgreSQL config_options),前端在「基本设置」提供精确 hostname 白名单编辑,并同步更新相关文档/变更记录。
  • 远程 Skill list / prepare / batch / search 改为在一次性 Provisioner Sandbox 中执行(inherit_env=False,Kubernetes 禁止自动挂载 ServiceAccount token),并新增 Sandbox → 宿主目录下载的边界校验与限额逻辑。
  • 增加/更新单元与集成测试,覆盖白名单、隔离执行、目录回流校验、超时与清理语义。

Reviewed changes

Copilot reviewed 25 out of 25 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
web/src/components/SkillSettingsSection.vue 新增远程来源白名单配置 UI(tags 输入、加载/保存)。
web/src/components/BasicSettingsSection.vue 在基本设置中挂载 Skill 配置区块。
docs/develop-guides/changelog.md 记录远程 Skill 来源策略与隔离执行变更。
docs/agents/skills-management.md 更新远程安装说明:白名单、Sandbox 执行、回流校验与限额。
docs/agents/sandbox-architecture.md 补充远程 Skill 拉取不继承环境变量与禁用 SA token 的说明。
docker/sandbox_provisioner/app.py Provisioner 创建 Sandbox 支持 inherit_env,K8s 禁用 SA token 挂载。
backend/test/unit/toolkits/test_install_skill.py 覆盖从 Sandbox 安装个人 Skill 的下载边界与线程卸载行为。
backend/test/unit/services/test_skill_service.py 更新远程 skill 准备接口的签名/传参断言。
backend/test/unit/routers/test_skill_router.py 覆盖 remote list 路由向下传递 db 会话参数。
backend/test/unit/config/test_options.py 覆盖 remote_skill_source_policy 的默认值、显式空列表与类型校验。
backend/test/unit/backends/test_sandbox_provisioner_config.py 覆盖 inherit_env 转发、Docker/K8s 禁用环境/SA token。
backend/test/unit/backends/test_sandbox_provisioner_client.py 覆盖 provisioner client 传递 inherit_env
backend/test/unit/backends/test_sandbox_download.py 新增 Sandbox 目录下载的越界/限额/清理语义测试。
backend/test/unit/backends/test_sandbox_backends.py 覆盖 provider 释放/锁回收、inherit_env 行为与超时传递。
backend/test/unit/agents/skills/test_remote_install.py 覆盖来源白名单规范化、一次性 Sandbox 执行与回流目录行为。
backend/test/integration/api/test_system_router_api.py 集成覆盖:remote_skill_source_policy 显式空列表可见与可恢复。
backend/server/routers/skill_router.py remote list 路由注入 db 并传递到服务层。
backend/package/yuxi/config/options.py 新增 remote_skill_source_policy 配置项;支持 list[str] 值保留与类型校验。
backend/package/yuxi/agents/toolkits/buildin/install_skill.py Sandbox 安装路径改用统一的目录下载校验逻辑,并线程卸载避免阻塞事件循环。
backend/package/yuxi/agents/skills/service.py 远程批量准备接口补充 db 参数传递。
backend/package/yuxi/agents/skills/remote_install.py 核心改造:白名单规范化校验 + 一次性无凭据 Sandbox 执行 + 目录回流下载。
backend/package/yuxi/agents/backends/sandbox/provisioner_client.py create 请求新增 inherit_env 字段。
backend/package/yuxi/agents/backends/sandbox/provider.py 支持 inherit_env;线程锁改 WeakValueDictionary;新增 release 清理缓存。
backend/package/yuxi/agents/backends/sandbox/download.py 新增 Sandbox 目录下载的路径校验、限额与失败清理实现。
backend/package/yuxi/agents/backends/sandbox/backend.py Sandbox backend 透传 inherit_env;execute 增加 HTTP 超时选项传递。

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread backend/package/yuxi/agents/skills/remote_install.py
Comment thread backend/package/yuxi/agents/backends/sandbox/download.py

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2e2f554421

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread backend/package/yuxi/agents/skills/remote_install.py Outdated
Comment thread backend/package/yuxi/agents/backends/sandbox/download.py
Comment thread backend/package/yuxi/agents/backends/sandbox/download.py
Comment thread backend/package/yuxi/agents/skills/remote_install.py Outdated
@xerrors
xerrors merged commit 771e7ce into xerrors:main Aug 12, 2026
4 checks passed
@xerrors
xerrors deleted the fix/remote-skill-source-allowlist branch August 12, 2026 07:17
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.

3 participants