Skip to content

sys_permission_set.active and sys_position.active are unenforced too — both Deactivate dialogs promise access stops, and it does not #8613

Description

@os-zhuang

Found while implementing #8535 (which withdraws the identical false claim on sys_capability only). Filed unassigned — out of scope for #8535's PR, which deliberately touches nothing but sys_capability.

#8535 established that sys_capability.active is read by nothing while its Deactivate dialog claims grants stop resolving. The same shape exists on the other two RBAC catalogue objects, and on those it is worse: a permission set and a position are the grant itself, not a catalogue entry.

The claims

sys-permission-set.object.ts, deactivate_permission_set:

Deactivate this permission set? Existing assignments stay in place but stop granting access until re-activated.

sys-position.object.ts, deactivate_position:

Deactivate this position? Users keep their assignment but the position stops granting permissions until re-activated.

Both ship translated into all four locales.

What actually happens (measured on b45c71e85a)

Nothing filters on active anywhere in the resolution chain:

  • SecurityPlugin.resolvePermissionSetsForContext (security-plugin.ts:3626) builds requested from context.positions + context.permissions plus the additive baseline. No active check.
  • PermissionEvaluator.resolvePermissionSets (permission-evaluator.ts:398) matches metadata sets by name, then bootstrap sets by name, then falls through to the DB loader. No active check in any of the three sources.
  • The DB loader (security-plugin.ts:812) queries sys_permission_set with where: { name: { $in: names } }no active predicate — and the row is mapped to a PermissionSet that does not carry active at all, so nothing downstream could filter on it even if it wanted to.
  • Every non-test sys_position row read (delegated-admin-gate.ts, security-plugin.ts, the bootstrap seeders) looks up by name or id. None reads active.

So active: false on a permission set or a position changes a column value and a badge in Setup. The assignments keep granting.

Why this is worth its own card

Same direction of falsehood as #8535, higher blast radius. An admin revoking a compromised or over-broad permission set is told in a confirmation dialog that access stopped; it did not. The admin's likely next action is to not do the thing that would actually work (delete the set, or remove the assignments).

Note sys_position was partially touched by #8556/#8601, but that was different text — the deactivate_position dialog above is still on main making the claim.

Not a recommendation

The direction is the same contract decision the maintainer already ruled on for sys_capability (2026-08-13, ADR-0049 enforce-or-remove, option B: withdraw the claim rather than put the registry on the authorization hot path). Whether that ruling extends to these two is not something this finding assumes: unlike a capability catalogue, a permission set's active flag has a plausible real enforcement point (the DB loader's where, one predicate) and a plausible real business pull (switching a grant off without deleting it). Both options are live and the trade-off is different from #8535's. Needs triage, not a rider.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions