Skip to content

Security Design

zhangxh edited this page Aug 16, 2026 · 1 revision

安全设计

本页说明 0.5.0 的安全目标、实现边界和仍需用户承担的责任。任何凭据管理都不能承诺“绝对安全”;正确理解边界比“已加密”三个字更重要。

安全目标

  • Token 静态存储不进入普通配置文件或仓库。
  • Token 不进入命令行参数、remote URL 或永久 Git 配置。
  • Token 只发送给用户明确连接且 URL 精确匹配的实例。
  • 平台返回的数据不能把认证 Git 操作重定向到外域或危险协议。
  • 工作区 Hook、过滤器和子模块不能在带 PAT 的认证环境中运行。
  • 错误、日志和展示 URL 尽量移除凭据。
  • 长操作期间仓库/分支/连接变化时停止,而不是继续使用过期选择。

Token 静态存储

Token 使用 ExtensionContext.secrets 保存。VS Code 桌面版通过 Electron safeStorage 提供平台加密;SecretStorage 不跨机器同步。

连接元数据使用扩展 globalState,结构中不包含 Token。修改/删除连接时,元数据与凭据没有原生跨存储事务,代码通过串行写入、修订号检查和失败补偿尽量保持一致。

官方参考:VS Code Common Capabilities:Data Storage

为什么不把加密 Token 写入 settings.json

如果自动同步的设备能自动解密,解密密钥也必须以某种形式可获得:

  • 密钥和密文一起同步,等同于把解密能力一起泄漏;
  • 密钥硬编码在扩展中,任何人都能提取;
  • 密钥仍放 SecretStorage,新机器没有密钥,失去同步意义;
  • 用户每次输入主密码,会引入复杂恢复、轮换和误操作风险。

因此 TriForge 选择设备本地 SecretStorage,每台设备输入一次 Token。

API 请求防护

  • 根据平台和实例首页 URL推导固定 API 根路径;
  • Token 使用平台要求的 Header,不放查询字符串;
  • 认证请求禁止自动重定向;
  • 流式限制响应大小;
  • 请求和错误有超时、取消与脱敏处理;
  • 仓库响应必须通过字段和 URL 验证。

在自动建库或克隆前,平台返回的 owner、仓库名、Web URL、clone URL 必须与预期实例和 namespace 一致。外域、危险协议、嵌入凭据、查询参数和 fragment 会被拒绝。

Git HTTPS 认证

TriForge 不把 Token 写成:

https://user:TOKEN@example.com/owner/repo.git

而是为单个 Git 子进程构造临时环境配置:

  • 范围限定的 http.<instance>.extraHeader
  • 清空 credential.helper
  • 关闭交互式凭据提示;
  • 限制允许的 Git 协议;
  • 禁止 HTTP 重定向;
  • 必要时使用一次性空 core.hooksPath

Git 子进程通过参数数组、shell: false 启动,降低 shell 注入风险。具体文件路径启用 literal pathspec,文件名里的 *?[ 不会被当成通配符。

这些临时配置依赖 Git 2.31+。

URL 匹配边界

PAT 只用于能够精确匹配连接实例的 HTTP(S) remote:

  • 主机匹配;
  • 路径前缀匹配;
  • 协议为 HTTP(S);
  • URL 不含嵌入凭据。

以下不会获得 PAT:

  • git@host:owner/repo.git SCP 风格地址;
  • ssh:// remote;
  • file://
  • ext:: 或自定义 remote helper;
  • 另一主机或不匹配路径前缀的 URL。

SSH remote 应使用 SSH Agent/Keychain 等独立认证流程。

Hook、Filter、LFS 与子模块隔离

Git 会把环境传给子进程。一个恶意 pre-push Hook、内容过滤器、LFS 程序或子模块命令理论上可能读取临时配置环境。

为降低风险:

  • 认证 Push 使用空 Hook 目录,并传递跳过 Hook 的 Git 选项;
  • Fetch 禁止递归子模块和自动维护;
  • 认证 Pull 把网络 Fetch 与无 Token 的本地合并阶段分开;
  • 认证 Clone 把网络下载与无 Token 的 Checkout 分开;
  • 认证 Clone/Push 不自动递归子模块;
  • LFS 需用项目认可的独立认证流程处理。

普通本地 Commit/Merge 没有平台 Token 环境,可能照常运行用户配置的 Git Hook。这些 Hook 仍是本地代码执行边界,打开不可信仓库时必须谨慎。

输出与日志

TriForge 尝试从 Git stdout/stderr、API 错误和 URL 展示中移除:

  • 原始 Token;
  • Basic 编码形式;
  • URL 中的用户名/密码;
  • 查询参数和 fragment。

脱敏不代表日志完全没有隐私信息。实例域名、用户名、仓库名、文件路径和错误上下文仍可能敏感。公开 Issue 前请人工检查。

工作区信任

扩展清单声明不支持未受信任和虚拟工作区。原因包括:

  • 会运行本机 Git;
  • Git 配置可能引用外部程序;
  • 本地操作可能触发 Hook;
  • 会访问私有平台和本机 SecretStorage。

不要为了让陌生仓库“能用”而随意授予信任。先审查仓库来源和内容。

高风险动作保护

  • 放弃文件更改:模态确认并复核文件指纹;
  • Hard Reset:额外不可恢复警告并复核工作区状态;
  • 强制删除未合并分支:默认二次确认;
  • 修改实例 URL:必须新 Token;
  • 删除连接:删除 SecretStorage 凭据但不动仓库 remote;
  • Pull:默认 --ff-only
  • 同步 Push:不自动 Force Push;
  • 长操作:反复验证仓库、HEAD、remote 和连接快照。

仍然存在的风险

  • Token 使用时必须短暂存在扩展宿主内存和 Git 子进程环境;同一用户权限下的恶意进程可能攻击运行时。
  • SecretStorage 保护静态数据,不防已经解锁的用户会话或恶意 VS Code 扩展。
  • HTTP 连接没有传输加密。
  • 企业代理、根 CA 或平台服务端本身可能观察 Token。
  • 平台 Token 权限过大时,泄漏影响更大。
  • 已经 Push 的机密不会因删除连接而从 Git 历史消失。
  • 多平台同步不是原子事务,部分成功无法自动回滚。

用户最佳实践

  • 使用最小权限、短有效期、按设备区分的 Token;
  • 操作私有代码时只安装可信扩展;
  • 保持 VS Code、Git、操作系统和托管平台更新;
  • 使用 HTTPS 和有效证书;
  • Push 前运行项目测试和 Secret Scanner;
  • 不把 Token 保存到 Git 配置或环境文件;
  • 设备丢失时立即撤销对应 Token;
  • 重要仓库保留独立备份,而不是把同步推送当成完整备份。

Clone this wiki locally