安全
OxideTerm 的界面、终端状态和核心服务由 Rust 与 GPUI 实现。安全边界还包括密码库、系统钥匙串、远端主机以及插件运行时,不能仅凭实现语言判断整个应用的安全性。
SSH 与密码学
Section titled “SSH 与密码学”OxideTerm 2.0.27 使用仓库内维护的 russh 0.63.0 和 russh-sftp 2.3.0,SSH 启用 russh 默认的 aws-lc-rs 加密后端。
- aws-lc-rs 调用原生 AWS-LC 密码库,因此不能宣称整个依赖树没有 C 或汇编代码
- 不依赖 libssh2,也不要求系统提供 OpenSSL 运行库
- 支持 SSH 密钥交换、通道、SFTP、转发,以及 ChaCha20-Poly1305、AES-GCM 等密码套件
- 敏感值使用零化容器,并限制复制、日志输出和持有时间
Rust 的内存安全机制有助于减少内存错误,但不能替代协议审查、依赖更新、主机密钥验证和凭据保护。
操作系统钥匙串
Section titled “操作系统钥匙串”所有敏感凭证存储在 操作系统原生钥匙串 中:
| 平台 | 钥匙串 |
|---|---|
| macOS | 钥匙串访问 |
| Windows | Windows 凭据管理器 |
| Linux | Secret Service API(GNOME Keyring / KWallet) |
密码、私钥口令和 API 密钥 绝不 存储在配置文件、数据库或明文中。
本地配置静态加密
Section titled “本地配置静态加密”并不是所有重要字段都适合直接塞进系统钥匙串,所以 OxideTerm 还会对本地保存的配置做静态加密。
- 磁盘上的本地配置以加密文档形式保存,而不是明文 JSON
- 专用的本地配置密钥保存在系统钥匙串中
- 连接元数据、跳板路由、标签等保存状态会在本地使用 ChaCha20-Poly1305 密封
- 较旧的明文配置会在启动时迁移到加密存储
实际效果是:真正的秘密放在系统钥匙串里,其余已保存连接状态在磁盘上也不会裸奔。
AI API 密钥
Section titled “AI API 密钥”OxideSens AI API 密钥存储在操作系统钥匙串的 com.oxideterm.ai 服务下,与 SSH 凭证分开存储。
在 macOS 上,受保护的钥匙串读取可以通过设备所有者认证(例如 Touch ID)授权。具体认证提示受系统策略和钥匙串访问状态影响。
连接导出加密
Section titled “连接导出加密”用于分享连接配置的 .oxide 导出格式使用:
- ChaCha20-Poly1305 — AEAD(带关联数据的认证加密)
- Argon2id — 内存硬化 KDF(密钥派生函数)
- 256 MB 内存开销
- 4 次迭代
- 抵抗 GPU/ASIC 暴力破解
- SHA-256 完整性校验和
- 可以选择是否在导出中包含受支持的凭据
- 包含凭据的载荷经过加密;导出前应核对包含的内容
- 可选密钥嵌入 — 私钥可 base64 编码后嵌入加密载荷
- 预检分析 — 导出前,OxideTerm 分析认证类型并检测缺失的密钥,让你清楚知道将导出什么内容
包含敏感数据的内存使用 zeroize 进行安全清除。
SSH 安全
Section titled “SSH 安全”主机密钥验证
Section titled “主机密钥验证”OxideTerm 实现 TOFU(首次使用时信任):
- 首次连接:接受并存储主机密钥
- 后续连接:与已存储的密钥进行验证
- 拒绝主机密钥变更 — 防止中间人攻击
- 使用
~/.ssh/known_hosts,行为与 OpenSSH 兼容
支持的密钥类型
Section titled “支持的密钥类型”- Ed25519(推荐——最快、最小的密钥)
- ECDSA(P-256, P-384)
- RSA(最低 2048 位)
- SSH 证书 — 完整的基于证书的认证支持
SSH Agent 集成
Section titled “SSH Agent 集成”OxideTerm 支持系统 SSH Agent 进行密钥管理:
| 平台 | Agent |
|---|---|
| macOS/Linux | SSH_AUTH_SOCK Unix Socket |
| Windows | \\.\pipe\openssh-ssh-agent Named Pipe |
功能:
- 重连时自动重放 Agent 认证
- 每个 ProxyJump 跳板可独立使用 Agent 认证
- 自定义
AgentSigner实现封装系统 Agent 并满足russh的Signertrait
原生进程边界
Section titled “原生进程边界”桌面界面、终端状态和领域服务位于同一个 Rust 进程中。终端字节直接更新 TerminalState,连接、SFTP、端口转发、IDE 和 AI 通过进程内调用协作,普通终端渲染不依赖本地 WebSocket 桥接;单独启用的 MCP 等集成具有各自的访问控制边界。
独立的 oxideterm CLI 直接读取指定配置目录并调用相同领域 crate;它不是桌面应用的远程控制客户端。
插件系统使用多层安全机制:
| 层次 | 机制 |
|---|---|
| WASM 沙箱 | WASM 插件在 wasmtime 中运行,不能获得任意宿主进程访问权 |
| 能力校验 | Host API 调用会核对清单声明和插件权限 |
| 路径约束 | 运行时入口必须位于插件目录内,拒绝路径逃逸 |
| 执行限制 | 宿主可中断超时或失败的插件执行,并记录诊断 |
| 原生界面 | 插件提交声明式界面数据,由宿主使用 GPUI 控件渲染 |
Wasm 插件通过受控 Host API 使用宿主能力,宿主会核对清单与权限。进程插件是原生可执行程序,不具备同样的 Wasm 沙箱边界;启用前应审查其来源、清单和请求的能力。
原生内容边界
Section titled “原生内容边界”OxideTerm 不加载网页界面,也没有 DOM、脚本注入或内容安全策略配置面。应用界面由本地 Rust 代码和 GPUI 绘制;插件也不能注入 HTML、CSS 或脚本。
- 无遥测 — OxideTerm 不收集或传输使用数据
- 默认本地优先 — 不要求账号,也不强制依赖云服务
- 本地优先 — AI 功能自带密钥
- 云工作流按需启用 — Cloud Sync 只有在你配置后才会访问远端后端,不是本地工作区的前置依赖
- 显式数据发送 — 终端缓冲区数据仅在你主动请求时(点击 Context 按钮并发送消息)才发送给 AI 服务商
- 本地 AI — 通过 Ollama 使用本地模型,AI 查询零网络流量
- 分层本地存储 — 设置、连接和配置使用 JSON 或加密文档存储;部分历史、索引和运行时状态使用本地 redb 数据库