// docs / baas security / firebase if-true explainer
Firebase allow read, write: if true 解释:它做什么以及如何修复
<code>allow read, write: if true;</code> 是生产中最常见的单一 Firebase 配置错误。它是创建新数据库时 Firebase 控制台建议的测试模式默认值、AI 编码工具从文档重新生成的规则,以及向互联网上任何人开放整个 Firestore 数据库的规则。本文精确解释语法、展示此规则有效时攻击者看到的内容,并给出四个适合不同用例的逐步更严格替换。
逐行解释语法
一个完整的 Firestore 测试模式规则文档是六行:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true;
}
}
}解码:
rules_version = '2';选择 v2 规则引擎 (当前)。较旧的 v1 规则已弃用。service cloud.firestore将块限定到 Firestore。Realtime Database 使用不同的基于 JSON 的语法;Cloud Storage 使用service firebase.storage。match /databases/{database}/documents绑定特殊的(default)数据库 (大多数项目只有一个)。match /{document=**}是递归通配符。**匹配任意深度的任意路径。与{document}结合,这捕获每个集合中的每个文档 — 一个 match 子句统治整个数据库。allow read, write: if true;是规则主体。read和write都被允许;条件if true嘛,永远为真。read涵盖get和list操作;write涵盖create、update和delete。
净效果:任何拥有 Firebase 项目 ID 和正确 SDK 的客户端都可以读取或写入任何集合中的任何文档。不需要身份验证。不强制速率限制。
Firebase 为何将此作为默认值
Firebase 希望你在创建项目后的前 30 秒内开始编码。替代方案 — 在任何读写工作之前让你编写正确的规则 — 会阻塞入门。所以控制台在你创建数据库时提供两个选项:生产模式 (拒绝一切,你自己写规则) 或测试模式 (30 天允许一切)。大多数开发者点击测试模式,然后忘了再去看。较旧的项目有 30 天计时器;当前项目有无自动过期的不确定 if true 规则。
结构性问题:AI 编码工具在显示测试模式规则的文档、教程和 Stack Overflow 答案上训练。当你问 Cursor 或 Claude Code「如何设置 Firebase」时,答案常常包含完全相同的 allow read, write: if true 块,仿佛它就是生产规则。AI 不知道 — 也没有被提示去知道 — 此规则对生产不安全。
攻击者看到什么
具体来说,知道你的 Firebase 项目 ID (可从任何已部署应用的包中 30 秒内提取) 并运行以下内容的攻击者,可以列出每个集合中的每个文档:
单个未认证 curl 请求就足以枚举每个集合。见下方高亮块。
curl 'https://firestore.googleapis.com/v1/projects/[project-id]/databases/(default)/documents:listCollectionIds' \
-X POST \
-H 'Content-Type: application/json' \
-d '{}'响应是顶层集合的完整列表。对每个集合,第二个请求返回文档。此路径没有速率限制,因为 if true 规则接受匿名流量。我们见过在不到一小时内被枚举的拥有数百万文档的 Firebase 数据库。
在写入路径上:带 {fields} 的单次 POST 创建新文档。攻击者可以用垃圾污染你的集合,污损从 Firestore 读取的用户面页面,或将你的数据库用作免费消息代理 — 你的使用账单飙升,你调查,账单解释了问题。
四个生产安全替代方案
选择匹配你应用数据模型的替代方案。所有四种都假设你有用户身份验证 (Firebase Auth 或任何发行 Firebase ID 令牌的提供商):
选项 1:用户拥有的文档
最常见的 SaaS 模式。文档位于 /users/{userId}/... 下,只有所有者可以接触它们。match /users/{userId}/{document=**} { allow read, write: if request.auth != null && request.auth.uid == userId; }
match /users/{userId}/{document=**} {
allow read, write: if request.auth != null
&& request.auth.uid == userId;
}选项 2:每个文档上的所有者字段
当文档位于扁平集合中 (未嵌套在用户 ID 下) 时,存储一个 owner_uid 字段并检查它。match /posts/{postId} { allow read: if resource.data.public == true || resource.data.owner_uid == request.auth.uid; allow write: if request.auth.uid == resource.data.owner_uid; }
match /posts/{postId} {
allow read: if resource.data.public == true
|| resource.data.owner_uid == request.auth.uid;
allow write: if request.auth.uid == resource.data.owner_uid;
}选项 3:多租户组织隔离
适用于具有组织范围数据的 B2B SaaS。在每个文档上存储 org_id 字段,并对照用户的自定义声明检查它。allow read, write: if request.auth.token.org_id == resource.data.org_id;。需要在注册期间通过 Firebase Admin SDK 设置自定义声明。
allow read, write: if request.auth.token.org_id == resource.data.org_id;
选项 4:只读公共内容
适用于营销内容、公共个人资料、产品目录 — 任何真正公开读取但仅管理员写入的内容。match /products/{productId} { allow read: if true; allow write: if request.auth.token.admin == true; }。admin 自定义声明只在管理员账户上设置。
match /products/{productId} {
allow read: if true;
allow write: if request.auth.token.admin == true;
}快速审计查询
在修复前,检查 if true 是否真的生效。打开 Firebase 控制台 → Firestore → Rules 并搜索 if true。如果你在注释之外的任何地方找到它,就有一项开放规则发现。同一 UI 中的规则模拟器让你在本地重放攻击者的请求 — 粘贴一个匿名 GET /users/somebody 并确认模拟器返回 允许。
外部确认:对你的生产 URL 运行 FixVibe 扫描。baas.firebase-rules 检查会探测你的 Firestore、Realtime Database 和 Storage 规则,并报告攻击者会发现的相同发现 — 独立于 Firebase 控制台显示的内容。
常见问题
<code>if true</code> 和 <code>if request.auth != null</code> 之间有什么区别?
if true 允许匿名访问 — 互联网上的任何人。if request.auth != null 需要任何登录用户,这更好但仍然错误:你应用的任何用户都能读取其他每个用户的数据。生产规则必须通过 request.auth.uid == resource.data.owner_uid 或类似方式限定到特定用户或组织。
Firebase 会自动让 <code>if true</code> 规则过期吗?
较旧项目 (2023 年前) 有 30 天计时器,会将 if true 规则转换为 if false。当前项目没有 — 规则会无限期存续,直到手动替换。如果你的项目在 2023 年前创建,规则看起来没问题,请仔细检查:计时器可能已将它们翻转为 if false,这会阻塞你自己的应用。
我可以使用未来日期时间戳检查作为安全网吗?
不能 — 时间戳条件不是安全控制。它在未来日期使开放规则过期,这意味着在那个日期之前攻击者拥有完全访问权。而你会忘记这个日期。用基于身份验证的规则替换 if true,而不是时间限制的规则。
如果我的应用真的是公开读取 (博客、产品目录) 怎么办?
那么明确地写 allow read: if true; allow write: if false; 仅在公共集合上 — 而不是数据库中的每个集合。每个集合使用单独的 match 子句,并且绝不在可写规则上使用递归 {document=**} 通配符。
后续步骤
对你的生产 URL 运行 FixVibe 扫描 — baas.firebase-rules 检查确认 if true 目前从公共互联网是否可利用。有关扫描器机制以及对 Realtime Database 和 Storage 的并行检测,请参阅 Firebase 规则扫描器。有关 Supabase 上的等效配置错误类别,请阅读 Supabase RLS 扫描器。
