6.1 默认安全策略与最小权限原则


上锁先立总纲。本节讲 Tauri 安全模型的第一性原理——默认拒绝与最小权限,说明三道默认防线各防住什么,并给"安全配置"一个新定位:它不是发布前的检查项,而是功能设计的输入。读懂总纲,后面三节的具体操作才有判断依据。

出发点:能力住在芯里

回想 2.1 的分层:页面的 JS 上下文里本来就没有文件、网络、进程能力——这些全部住在 Rust 芯。前端想用,只能经命令或插件 API 跨桥,而桥上驻着权限闸门(2.2 的第三站)。这个架构决定带来一个关键性质:WebView 里跑的任何脚本,能做的事完全等于闸门放行的事。恶意脚本不是"破解你的文件系统",而是"冒充你的前端去叫命令"——安全问题的形状从"防线被攻破"变成了"门禁被冒用",而门禁冒用是权限管理问题,权限管理有成熟解法。

三道默认防线

防线一:能力默认关闭。 未经 Capabilities 授权的插件命令,调用直接被拒。对比"默认全开、靠开发者自觉关闭"的模型,默认拒绝的错误方向是"少给了功能"——症状明显(功能不工作),开发期就暴露;默认全开的错误方向是"多给了权限"——症状是静默的,可能上线很久都没人发现。错误方向朝哪边偏,决定了系统是越用越严还是越用越松。

防线二:CSP 默认收紧。 生产构建自动注入内容安全策略,默认只许加载自身资源(3.3 的 security 段)。外链脚本、内联事件处理器这些经典注入通道在默认策略下失效。

防线三:上下文隔离。 Tauri 的 IPC 层不把 Rust 对象或句柄暴露到页面全局;前端拿到的只有异步调用接口。即便脚本在页面里拿到了 invoke 的引用,它能调到的也只限于授权集合内的命令名,拿不到任何底层对象。

三道防线的共同点是不需要你记得开启。安全机制分两种:一种是"默认在、可以关",一种是"默认没、记得开"。Tauri 的核心防线属于前者——这是它与"给开发者发一份安全清单自觉执行"方案的本质差别。

防线的"默认"长什么样,值得在动手前看一眼实物。新建项目的权限目录里只有一份最小清单,指向一个空权限集:

# capabilities/default.json —— 脚手架给出的起点 identifier: default windows: [main] permissions: []

permissions 为空意味着此刻前端连一个系统调用都做不了——invoke 任何插件命令都会吃到权限拒绝。这不是故障,是总纲的具象化:起点是零,每一个能力都必须经过显式申请才进入清单。对照"默认全开"方案那份动辄几十行的预授权列表,两种起点的差别就是两种安全姿态的差别。三道防线里,第一道归 6.2 的 Capabilities 机制管,第二道归 6.3 的 CSP 配置管,第三道由框架内建、无需配置——本节的义务是记住它们的边界,后续两节负责把前两道拧到合适的松紧。

最小权限原则的操作化

原则人人会背,难在操作化。给三条可执行的判据:

判据一:按功能授权,不按插件授权。 需要"保存对话框"不等于需要 dialog 插件全部命令——只授 save,不授 message、ask、confirm。粒度到命令级,不是到插件级。

判据二:按窗口授边界。 主窗需要读写笔记目录,关于窗口什么都不需要——权限文件按窗口分开写,别用一张大而全的清单喂所有窗口。第 4 章的多窗口标签在这里变成安全边界。

判据三:路径授权到目录级。 授 fs 读权限时给具体目录作用域(笔记目录),不给整个用户目录,更不给通配全盘。作用域的具体写法在 6.2 展开。

一次红队推演:注入脚本到底能偷走什么

判据好不好用,要放到攻击面前量一量。假设笔记应用渲染层出了一条漏报的注入:用户导入了一份来路不明的笔记文件,里面的批注字段藏了一段脚本,渲染时被当成 HTML 执行了。现在攻击者的代码已经跑在页面里,接下来会发生什么?

它第一件事通常是摸家底:试着调 window.__TAURI__。在 Tauri 2 里这个全局对象默认根本不注入,脚本能拿到的只有桥接层挂上的最小 invoke 入口。它转而直接叫命令名,推演结果取决于权限清单长什么样:

攻击动作 默认拒绝清单下 一张"图省事"的全开清单下
调用未授权的插件命令 桥上直接拒绝,返回权限错误 命令执行,文件被读走
读笔记目录之外的路径 作用域拦截,路径越界报错 全盘可读,凭据文件遭殃
加载外部脚本加深攻击 CSP 拦截外链,脚本无法二段加载 远程代码自由进入
探测底层 Rust 对象 上下文隔离,拿到的只有异步接口 视集成方式而定,可能暴露句柄

这张表左列是同一只红队,右列的差异完全由权限决策决定——这正是"门禁被冒用"这个定性想说的:**注入能否升级成事故,不取决于注入本身,取决于闸门后面有什么。**全开清单的持有者不是没有安全机制,而是把机制配置成了不设防;默认拒绝的持有者即便漏了净化,攻击者拿到的也只是一个空房间。推演还能再进一步:即便清单里确实有 fs 读权限(笔记应用总得读文件),6.2 的目录作用域也会把损失压在笔记目录内——攻击者读完笔记,仅此而已。安全设计做不到消灭漏洞,能做到的是给每一个漏洞标定天花板。

安全作为设计输入:三个前移

总纲的最后一块拼图,是把安全决策前移到功能设计期:

  • 命令签名设计:让命令收"笔记 id"而不是"任意路径"——越界检查自动消失,因为 id 根本构不成路径。参数设计即安全设计(5.3 的 ensure_within 是兜底,不是首选)。
  • 数据流设计:不可信内容(用户粘贴的富文本、外部导入的文件)从进入应用到落盘,标注一条"不可信数据流",渲染前净化、存储时隔离。
  • 窗口划分:需要展示外部内容的窗口(更新日志、帮助页)单独开窗口、单独配权限,与主窗隔离——窗口是最便宜的安全边界。

图 6-1:三道默认防线与红队路径

图 6-1:三道默认防线与红队路径

本节要点回顾

  • 能力住芯里:脚本能力上限等于闸门放行集,安全问题是权限管理问题;
  • 三道默认防线:能力默认关闭、CSP 默认收紧、上下文隔离,均无需记忆开启;
  • 默认拒绝优于默认全开:错误方向朝"少给"偏,暴露在开发期而非生产期;
  • 最小权限三判据:按功能授权、按窗口划边界、路径授到目录级;
  • 安全前移:命令收 id 不收路径、标注不可信数据流、窗口即信任域。

总纲立好。下一节动手写权限文件:给随身笔记发放第一张门禁卡,再收回两张发多了的。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U