跳转到正文
报告库
用途分类 / 其他用途

Better Auth Security Best Practices Skill 安全审计

作者说它能做什么(原文)

Configure rate limiting, manage auth secrets, set up CSRF protection, define trusted origins, secure sessions and cookies, encrypt OAuth tokens, track IP addresses, and implement audit logging for Better Auth. Use when users need to secure their auth setup, prevent brute force attacks, or harden a Better Auth deployment.

第三方安全检查结论

发现安全风险

已检查文件
1
发现的风险
5
会不会运行危险命令?检查是否下载程序后直接运行、让他人远程控制电脑,或藏起要运行的命令。未发现风险
会不会泄露文件和密钥?检查是否发送含密码或密钥的文件,以及代码里是否直接写了密钥。发现 2 项风险
中风险

跨子域 Cookie 示例会把会话凭据暴露给所有匹配子域

原文依据:1 处
发现了什么

示例为 .example.com 启用跨子域 Cookie,并明确加入 session_token 和 session_data。域级 Cookie 会随匹配请求发送到子域;HttpOnly 不能阻止被攻陷的子域服务器接收请求中的 Cookie。

为什么需要注意

一个不受完全信任或被接管的子域可能收到会话 Cookie,进而导致账号会话泄露或冒用。

这段代码的正常用途

候选描述的 Cookie 作用域后果在技术上可能发生,但原文把它作为“跨子域共享认证”的可选配置,并紧接着明确要求只有在确有共享需求且信任所有子域时才启用。因此,这不是隐蔽的数据外传指令,而是带有关键边界提示的功能示例。剩余风险取决于用户是否真的能保证所有当前及未来子域都可信;用户可要求作者进一步说明子域接管和受陷子域的影响。

这项判断针对展示的代码和适用条件,不表示风险已经实际发生。
SKILL.md:203来自说明文档打开原文件
### Cross-Subdomain Cookies```tsadvanced: {  crossSubDomainCookies: {    enabled: true,    domain: ".example.com", // Note the leading dot    additionalCookies: ["session_token", "session_data"],  },}```Only enable if you need authentication sharing and trust all subdomains.
中风险

审计示例收集个人信息但未规定日志保护和保留期限

原文依据:2 处
发现了什么

钩子把 IP、User-Agent、旧邮箱和新邮箱发送给 auditLog,但没有说明该函数把数据传到哪里、谁能访问、保存多久或如何脱敏。

为什么需要注意

若日志进入第三方服务、宽权限控制台或长期存储,用户身份及网络信息可能被不必要地披露,并扩大数据泄露和合规影响。

示例在会话创建时把 IP 和 User-Agent 传给未定义的 `auditLog`,在邮箱变更时记录旧、新邮箱。这些是可识别或可关联个人的数据,而可见文本没有限定日志目的地、访问权限、脱敏或保留期。若用户直接采用并由 `auditLog` 持久化或外发,可能扩大隐私、泄露和合规风险。用户可要求作者说明最小化字段、可信代理处理、访问控制、加密及删除期限。

SKILL.md:271来自说明文档打开原文件
      create: {        after: async ({ data, ctx }) => {          await auditLog("session.created", {            userId: data.userId,            ip: ctx?.request?.headers.get("x-forwarded-for"),            userAgent: ctx?.request?.headers.get("user-agent"),          });        },
查看另外 1 个位置
SKILL.md:287来自说明文档打开原文件
      update: {        after: async ({ data, oldData }) => {          if (oldData?.email !== data.email) {            await auditLog("user.email_changed", {              userId: data.id,              oldEmail: oldData?.email,              newEmail: data.email,            });          }        },
会不会删除文件或一直在后台运行?检查是否大范围删除文件、改写磁盘,或设置自动启动。未发现风险
会不会绕过安全保护?检查是否跳过网站安全验证、开放过多文件权限,或取消操作前的确认。发现 3 项风险
中风险

宽泛或动态的可信来源可能接受攻击者控制的子域名

原文依据:4 处
发现了什么

示例允许通配符子域名,并展示了根据请求动态生成可信来源,但没有展示租户允许列表或所有权验证。这些来源还用于验证回调和重定向 URL。

为什么需要注意

如果匹配范围内有可被攻击者注册、接管或控制的子域名,该域名可能通过来源检查,并被接受为认证回调或重定向目的地。

这是配置示例而非自动执行的代码,但风险成立:通配符会信任匹配的全部子域;动态示例又直接把请求派生的 tenant 插入来源,注释仅笼统要求验证,没有展示允许列表或租户所有权检查。由于同一可信来源集合用于校验回调和重定向地址,若用户照搬且攻击者能控制某个匹配子域或 tenant 值,可能扩大可接受的认证跳转范围。用户可要求作者补充严格允许列表、规范化及所有权验证。

SKILL.md:129来自说明文档打开原文件
```tstrustedOrigins: [  "*.example.com", // Matches any subdomain  "https://*.example.com", // Protocol-specific wildcard  "exp://192.168.*.*:*/*", // Custom schemes (e.g., Expo)]```
查看另外 3 个位置
SKILL.md:139来自说明文档打开原文件
Compute trusted origins based on the request:```tstrustedOrigins: async (request) => {  // Validate against database, header, etc.  const tenant = getTenantFromRequest(request);  return [`https://${tenant}.myapp.com`];}```
SKILL.md:149来自说明文档打开原文件
Validates `callbackURL`, `redirectTo`, `errorCallbackURL`, `newUserCallbackURL`, and `origin` against trusted origins. Invalid URLs receive 403.
SKILL.md:142来自说明文档打开原文件
```tstrustedOrigins: async (request) => {  // Validate against database, header, etc.  const tenant = getTenantFromRequest(request);  return [`https://${tenant}.myapp.com`];}```
中风险

直接采用转发 IP 请求头可能让客户端绕过按 IP 的限制

原文依据:2 处
发现了什么

配置把 x-forwarded-for 和 x-real-ip 用于 IP 跟踪及速率限制。这些请求头可由客户端伪造,除非应用只能通过可信代理访问,且代理会清除并重写外部值。

为什么需要注意

攻击者可能轮换伪造 IP 来规避登录限流;审计记录也可能把错误 IP 归给其他用户,降低调查可靠性。

示例明确把两个可由请求携带的转发头用于 IP 识别,并说明 IP 跟踪服务于限流。来源只对另一个 `trustedProxyHeaders` 设置给出“仅限可信反向代理”的警告,没有解释必须阻止客户端直连、清除外来头或只采用可信代理追加的地址。若部署边界未做到这些,客户端可能伪造或轮换头值,削弱按 IP 限流和审计归因。用户可要求作者说明可信代理链及头部清洗要求。

SKILL.md:250来自说明文档打开原文件
export const auth = betterAuth({  advanced: {    ipAddress: {      ipAddressHeaders: ["x-forwarded-for", "x-real-ip"], // Headers to check      disableIpTracking: false, // Keep enabled for rate limiting    },  },});```
查看另外 1 个位置
SKILL.md:260来自说明文档打开原文件
Set `ipv6Subnet` (128, 64, 48, 32; default 64) to group IPv6 addresses. Enable `trustedProxyHeaders: true` only if behind a trusted reverse proxy.
中风险

移动端建议允许跳过 OAuth state Cookie 检查

原文依据:2 处
发现了什么

指南允许无法维持 Cookie 的移动应用设置 skipStateCookieCheck: true,但没有同时要求使用等效的、与发起设备绑定的一次性 state 验证。PKCE 保护授权码交换,并不替代所有 state 的登录请求关联作用。

为什么需要注意

若应用仅关闭检查而没有替代验证,攻击者可能更容易发起登录 CSRF、错误账号绑定或把他人的 OAuth 响应注入受害者流程。

原文先说明 OAuth 默认使用 PKCE 和短期随机 state,随后允许无法维护 Cookie 的移动应用启用 `skipStateCookieCheck: true`,但可见内容没有要求用一次性、绑定发起设备或应用实例的机制替代该 Cookie 关联检查。若该选项确实跳过唯一的本地关联检查,攻击者可能更容易造成登录流程混淆或登录 CSRF。它仅是有条件建议,不代表攻击已经发生;用户可要求作者给出移动端等效校验的完整方案。

SKILL.md:219来自说明文档打开原文件
PKCE is automatic for all OAuth flows. State tokens are 32-char random strings expiring after 10 minutes.
查看另外 1 个位置
SKILL.md:241来自说明文档打开原文件
Enable if storing OAuth tokens for API access on behalf of users. Use `skipStateCookieCheck: true` only for mobile apps that cannot maintain cookies.
会不会误导 AI 或隐藏内容?检查工作说明是否要求 AI 忽略你的指令、干扰检查结果,或夹带看不见的文字。未发现风险
会不会偷偷改推广链接或收款方?检查是否强制替换推广链接或收款对象,同时要求隐瞒更改。未发现风险

Skill 逻辑拆解

8 个说明模块

该 Skill 是 Better Auth 安全配置指南,提供可复制的 TypeScript 配置片段;所示内容依赖用户把片段加入应用后才会生效。

查看原文
SKILL.md:10来自说明文档打开原文件
```tsimport { betterAuth } from "better-auth";export const auth = betterAuth({  secret: process.env.BETTER_AUTH_SECRET, // or via `BETTER_AUTH_SECRET` env});```

指南推荐生产环境启用速率限制和 CSRF 检查,并使用环境变量保存认证密钥。

查看原文
SKILL.md:18来自说明文档打开原文件
Better Auth looks for secrets in this order:1. `options.secret` in your config2. `BETTER_AUTH_SECRET` environment variable3. `AUTH_SECRET` environment variable### Secret Requirements- Rejects default/placeholder secrets in production- Warns if shorter than 32 characters or entropy below 120 bits- Generate: `openssl rand -base64 32`- Never commit secrets to version control
SKILL.md:100来自说明文档打开原文件
export const auth = betterAuth({  advanced: {    disableCSRFCheck: false, // Default: false (keep enabled)  },});```Only disable for testing or with an alternative CSRF mechanism.

指南包含审计钩子示例,会把用户标识、IP、User-Agent 及邮箱变更信息交给未定义的 auditLog 实现。

查看原文
SKILL.md:271来自说明文档打开原文件
      create: {        after: async ({ data, ctx }) => {          await auditLog("session.created", {            userId: data.userId,            ip: ctx?.request?.headers.get("x-forwarded-for"),            userAgent: ctx?.request?.headers.get("user-agent"),          });        },
SKILL.md:287来自说明文档打开原文件
      update: {        after: async ({ data, oldData }) => {          if (oldData?.email !== data.email) {            await auditLog("user.email_changed", {              userId: data.id,              oldEmail: oldData?.email,              newEmail: data.email,            });          }
从这里开始 · 工作说明SKILL.md
better-auth-security-best-practices
连线表示工作说明包含的模块,不是实际运行顺序。点击模块可查看原文。 另有 5 个章节,可在原文件中查看。
文件与检查记录1 个文件

检查范围与遗漏

逐文件查看涉及的内容

下方列出本次涉及的原文范围;纳入检查不代表已查清所有问题。

  • SKILL.md已纳入全文

这份报告只针对上方版本。我们看了拿到的代码和说明文件,没有实际运行 Skill,也没有检查它另外安装的软件包。因此,这不是“保证安全”的承诺;换了版本或使用环境,结果也可能不同。

  • SKILL.md工作说明

代码和说明中提到的操作

读取密钥或账号配置
SKILL.md:14来自说明文档打开原文件
export const auth = betterAuth({  secret: process.env.BETTER_AUTH_SECRET, // or via `BETTER_AUTH_SECRET` env});
SKILL.md:337来自说明文档打开原文件
Built-in: consistent response messages, dummy operations on invalid requests, background email sending. Return generic error messages ("Invalid credentials") rather than specific ones ("User not found").
SKILL.md:345来自说明文档打开原文件
export const auth = betterAuth({  secret: process.env.BETTER_AUTH_SECRET,  baseURL: "https://api.example.com",
连接外部网站
SKILL.md:117来自说明文档打开原文件
export const auth = betterAuth({  baseURL: "https://api.example.com",  trustedOrigins: [
SKILL.md:119来自说明文档打开原文件
  trustedOrigins: [    "https://app.example.com",    "https://admin.example.com",
SKILL.md:120来自说明文档打开原文件
    "https://app.example.com",    "https://admin.example.com",  ],
读取了多少行
433
文件校验值(用于核对版本)
5f6ddb851ceee643414802b185180fbdf33a7d2440403c7a3fdbe5e4a7c5c0b4