-
Notifications
You must be signed in to change notification settings - Fork 0
Security Design
本页说明 0.5.0 的安全目标、实现边界和仍需用户承担的责任。任何凭据管理都不能承诺“绝对安全”;正确理解边界比“已加密”三个字更重要。
- Token 静态存储不进入普通配置文件或仓库。
- Token 不进入命令行参数、remote URL 或永久 Git 配置。
- Token 只发送给用户明确连接且 URL 精确匹配的实例。
- 平台返回的数据不能把认证 Git 操作重定向到外域或危险协议。
- 工作区 Hook、过滤器和子模块不能在带 PAT 的认证环境中运行。
- 错误、日志和展示 URL 尽量移除凭据。
- 长操作期间仓库/分支/连接变化时停止,而不是继续使用过期选择。
Token 使用 ExtensionContext.secrets 保存。VS Code 桌面版通过 Electron safeStorage 提供平台加密;SecretStorage 不跨机器同步。
连接元数据使用扩展 globalState,结构中不包含 Token。修改/删除连接时,元数据与凭据没有原生跨存储事务,代码通过串行写入、修订号检查和失败补偿尽量保持一致。
官方参考:VS Code Common Capabilities:Data Storage。
如果自动同步的设备能自动解密,解密密钥也必须以某种形式可获得:
- 密钥和密文一起同步,等同于把解密能力一起泄漏;
- 密钥硬编码在扩展中,任何人都能提取;
- 密钥仍放 SecretStorage,新机器没有密钥,失去同步意义;
- 用户每次输入主密码,会引入复杂恢复、轮换和误操作风险。
因此 TriForge 选择设备本地 SecretStorage,每台设备输入一次 Token。
- 根据平台和实例首页 URL推导固定 API 根路径;
- Token 使用平台要求的 Header,不放查询字符串;
- 认证请求禁止自动重定向;
- 流式限制响应大小;
- 请求和错误有超时、取消与脱敏处理;
- 仓库响应必须通过字段和 URL 验证。
在自动建库或克隆前,平台返回的 owner、仓库名、Web URL、clone URL 必须与预期实例和 namespace 一致。外域、危险协议、嵌入凭据、查询参数和 fragment 会被拒绝。
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+。
PAT 只用于能够精确匹配连接实例的 HTTP(S) remote:
- 主机匹配;
- 路径前缀匹配;
- 协议为 HTTP(S);
- URL 不含嵌入凭据。
以下不会获得 PAT:
-
git@host:owner/repo.gitSCP 风格地址; -
ssh://remote; -
file://; -
ext::或自定义 remote helper; - 另一主机或不匹配路径前缀的 URL。
SSH remote 应使用 SSH Agent/Keychain 等独立认证流程。
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;
- 重要仓库保留独立备份,而不是把同步推送当成完整备份。
当前文档对应 TriForge Git 0.5.1。