Filed unassigned by the domain:services execution seat (session session_01APWX2AwT3a4xDcjPCe8bk4)。⛔ 不认领,定级归 triage;修法方向属 Clause-② 且是安全边界,维护者地板。
出处:#11074 派发时要求的「同轮测量,只报不改」
派 #11074 时我写了一条同轮测量要求,并明确 ⛔ 不要把修复扩散到 /admin/* —— 扩散会把一个范围清晰的安全修复变成不可评审的。dev 照办了:PR #11475 只动 /delete-user,把 /admin/* 的排序追踪出来、写进报告、不碰。本卡就是那份测量。
⚠️从代码读出的排序,不是执行出来的利用。 下面的后果按此口径陈述。
机制
break-glass 守卫注册为全局 hooks.before。better-auth 在每个端点自己的 use: [...] 中间件之前运行全局 before-hook。
/admin/remove-user 由 better-auth 自己的路由器直接服务,它的 adminMiddleware只做会话检查,真正的角色判定还要更晚 —— 在端点处理器内部才发生。
⇒ 对一个已认证的非管理员调用者,守卫自身的查找与可能的拒绝,发生在上述两道检查都还没跑之前。
⭐ 与 /admin/ban-user 的对照,才是这张卡的精确之处
同一个守卫,两条路由,排序相反:
| 路由 | 排序 | 原因 |
|---|
/admin/remove-user | 守卫 先于 授权 | 由 better-auth 路由器直接服务,无 ObjectStack 侧前置门 |
/admin/ban-user | 授权 先于 守卫 | #9652 用 auth-plugin.ts 的 raw mount 遮蔽了它,gateAdmin(c) 在重跑守卫之前授权 |
⇒ 这不是「守卫设计得不好」,而是其中一条路由缺少另一条已经有的那层遮蔽挂载。差别来自 #9652 的补丁覆盖面,不是来自守卫本身。
⚠️因此本卡与 #9652 是耦合的:改动那些 raw mount(取消遮蔽、或改变遮蔽范围)会双向改变这里的排序。谁先动,另一张的结论就要重测。⛔ 不要在不看本卡的情况下改 #9652 的挂载面,反之亦然。
与已有三张卡的关系:同一守卫的第三张面孔
| 卡 | 路由 | 需要什么 | 状态 |
|---|
| #10776 | /delete-user | 无需认证 | ✅ 已修已关 |
| #11074 | /delete-user | 任意已认证调用者 | ✅ PR #11475(在评审中) |
| 本卡 | /admin/remove-user | 任意已认证非管理员 | 🆕 |
前两张是同一条路由上门槛的收窄。本卡是另一条路由,同类形状:守卫在授权之前就对一个由请求指名的目标做了判断,而它的拒绝本身携带信息。
⛔ 不要把本卡读成「#11475 没修好」。#11475 修的是 /delete-user,并且修完了;本卡从一开始就被排除在其范围之外,是刻意的,理由写在 #11074 的派发词里。
已被 #11475 排除的、以及本卡未做的
披露纪律
本卡只描述机制与排序,与 #10776 / #11074 已公开的范围一致。⛔ 不含请求形状、构造步骤或可复现的读取示例。
Refs:#11074 · PR #11475(测量出处)· #10776 · #9652(耦合)· #9969 · ADR-0068
Filed unassigned by the
domain:servicesexecution seat (sessionsession_01APWX2AwT3a4xDcjPCe8bk4)。⛔ 不认领,定级归 triage;修法方向属 Clause-② 且是安全边界,维护者地板。出处:#11074 派发时要求的「同轮测量,只报不改」
派 #11074 时我写了一条同轮测量要求,并明确 ⛔ 不要把修复扩散到
/admin/*—— 扩散会把一个范围清晰的安全修复变成不可评审的。dev 照办了:PR #11475 只动/delete-user,把/admin/*的排序追踪出来、写进报告、不碰。本卡就是那份测量。机制
break-glass 守卫注册为全局
hooks.before。better-auth 在每个端点自己的use: [...]中间件之前运行全局 before-hook。/admin/remove-user由 better-auth 自己的路由器直接服务,它的adminMiddleware只做会话检查,真正的角色判定还要更晚 —— 在端点处理器内部才发生。⇒ 对一个已认证的非管理员调用者,守卫自身的查找与可能的拒绝,发生在上述两道检查都还没跑之前。
⭐ 与
/admin/ban-user的对照,才是这张卡的精确之处同一个守卫,两条路由,排序相反:
/admin/remove-user/admin/ban-userauth-plugin.ts的 raw mount 遮蔽了它,gateAdmin(c)在重跑守卫之前授权⇒ 这不是「守卫设计得不好」,而是其中一条路由缺少另一条已经有的那层遮蔽挂载。差别来自 #9652 的补丁覆盖面,不是来自守卫本身。
与已有三张卡的关系:同一守卫的第三张面孔
/delete-user/delete-user/admin/remove-user前两张是同一条路由上门槛的收窄。本卡是另一条路由,同类形状:守卫在授权之前就对一个由请求指名的目标做了判断,而它的拒绝本身携带信息。
⛔ 不要把本卡读成「#11475 没修好」。#11475 修的是
/delete-user,并且修完了;本卡从一开始就被排除在其范围之外,是刻意的,理由写在 #11074 的派发词里。已被 #11475 排除的、以及本卡未做的
披露纪律
本卡只描述机制与排序,与 #10776 / #11074 已公开的范围一致。⛔ 不含请求形状、构造步骤或可复现的读取示例。
Refs:#11074 · PR #11475(测量出处)· #10776 · #9652(耦合)· #9969 · ADR-0068