人人都会AI编程

22.2 文件系统安全:路径遍历防护、权限最小化

更新时间:2026-07-11

在桌面应用中,文件系统是最敏感的资源之一。一旦被恶意利用,攻击者可能读取用户私密文件、覆盖系统配置,甚至执行任意代码。Tauri 从设计层面提供了两层防护:权限最小化路径遍历防护,让开发者能安全地暴露文件操作能力给前端。


1. 权限最小化:只给应用真正需要的目录

tauri.conf.json 中,你可以通过 fs 配置项明确声明应用允许读写的目录范围(也称为 fs scope)。例如,一个笔记应用只需要访问用户的文档目录和应用自己的数据目录:

{
  "tauri": {
    "allowlist": {
      "fs": {
        "scope": {
          "allow": [
            "$DOCUMENT/**",
            "$APPDATA/myapp/**"
          ],
          "deny": [
            "$DOCUMENT/secret/**"
          ]
        }
      }
    }
  }
}

关键点

  • allow 定义了白名单路径,支持通配符 ** 递归匹配,以及预设变量(如 $DOCUMENT$APPDATA$HOME)。
  • deny 可以在白名单内进一步排除敏感子目录。
  • 未明确声明的路径操作(如尝试读取 C:\Windows\System32\config\SAM)会被 Rust 后端直接拒绝,前端收到的只是一个权限拒绝错误,不会触及底层文件系统。

这种“先声明再使用”的模式,确保即使前端代码中存在任意文件读取漏洞,攻击者也无法越界访问。

2. 路径遍历防护:堵死 ../ 绕过

权限声明只是第一道防线。恶意输入仍可能借助 ../ 或绝对路径符号链接来尝试绕过白名单。Tauri 的 Rust 后端在每次文件操作前都会执行严格的路径规范化与边界检查,核心逻辑如下:

  1. 解析为绝对路径:将请求的相对路径(来自前端)与白名单允许的基路径结合,并通过 std::fs::canonicalize 解析出无 ..、无符号链接的最终真实路径。
  2. 验证是否在白名单内:检查解析后的真实路径,是否以某个允许的目录为前缀。如果不是,立即拒绝。
  3. 处理符号链接:即使攻击者试图在允许的目录内创建一个指向系统文件的符号链接,canonicalize 也会解析到目标文件,从而暴露它不在允许范围内。

示例(Rust 端自定义检查)
如果你需要更精细的控制,可以在自定义命令中手动调用 tauri::api::path::resolve_path 并获得安全上下文,但通常直接使用 Tauri 提供的 fs API 就足够了,因为它们已经内置了上述校验。

3. 最佳实践与常见陷阱

  • 永远不要在 allow 中使用 $HOME/$ROOT/

这等于把整个用户目录或系统根目录暴露给前端,形同虚设。始终限定到具体应用数据子目录。

  • 使用变量而非硬编码路径

$DOCUMENT$DOWNLOAD 等标准化变量能跨平台自动映射到正确位置,避免写死 Windows 的 C:\Users\... 或 macOS 的 /Users/...

  • 区分读写权限

scope 中,你可以进一步限制某条路径只允许读取(read: true)或写入(write: true),避免不必要的写入权限。

  • 警惕前端拼接路径

如果允许用户输入文件名,前端要简单过滤 ../,但不要依赖前端校验,Rust 后端的边界检查才是最终防线。

  • 测试边界情况

../../etc/passwd./..\..\Windows\System32\config\SAM 等典型攻击向量测试你的应用,确保返回的是“Permission denied”而不是文件内容。

4. 一个真实的安全示例

假设你的应用需要让用户选择并读取 $DOCUMENT 下的一个文本文件,你可以这样写前端调用:

import { readTextFile } from '@tauri-apps/api/fs';

// 用户选择的文件名(可能被篡改)
const userInput = "../../secret/data.txt";

try {
  const content = await readTextFile(`$DOCUMENT/${userInput}`);
  console.log(content);
} catch (error) {
  console.error("读取被拒绝:", error); // 路径遍历会被拦截
}

在 Rust 后端,Tauri 会检测到解析后的路径超出了 $DOCUMENT 范围,抛出错误,不会执行实际读取。

总结
文件系统安全不能靠“信任前端”来保证。Tauri 通过 scope 权限声明实现最小化授权,并在底层强制路径规范化与白名单比对,彻底阻断路径遍历攻击。你只需要在配置中精确声明应用所需目录,剩下的安全检查就交给了框架。