fix(plan/C1): close Admin→Owner escalation in enforce_owner_only_elevation
Spot-check of the new H-C1 hook code found the owner-only-elevation gate was bypassable: it skipped any member ALREADY privileged in the parent, but since Admin is also "privileged", an Admin→Owner promotion was skipped and accepted — the exact escalation the gate exists to stop, and a failure of its own paired test. Gate now skips only UNCHANGED roles (parent role == new role), so every change into a privileged role (Member→Admin/Owner, Admin→Owner, new privileged member) requires an owner signer. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4583,12 +4583,14 @@ fn enforce_owner_only_elevation(
|
||||
if !is_privileged(m.role) {
|
||||
continue;
|
||||
}
|
||||
// Privileged now. Was it already privileged in the parent (no change)?
|
||||
let already = parent_role(m.member_id.as_str())
|
||||
.map(is_privileged)
|
||||
.unwrap_or(false);
|
||||
if already {
|
||||
continue; // not an introduction or elevation
|
||||
// Privileged now. Skip ONLY if the role is unchanged from the parent
|
||||
// (a no-op same-role entry). Any CHANGE into a privileged role — a new
|
||||
// privileged member, Member→Admin/Owner, or Admin→Owner — must be
|
||||
// owner-signed. (A naive "already privileged" skip is WRONG: Admin is
|
||||
// also privileged, so it would let an Admin be elevated to Owner
|
||||
// unchecked — the exact escalation this gate exists to stop.)
|
||||
if parent_role(m.member_id.as_str()) == Some(m.role) {
|
||||
continue; // unchanged role — not an introduction or elevation
|
||||
}
|
||||
// A new owner/admin, or a member elevated to owner/admin → owner-only.
|
||||
if !signer.role.can_manage_owners() {
|
||||
|
||||
Reference in New Issue
Block a user