fix: the ACL answers the actions the controllers ask about - #877
Merged
blaipr merged 1 commit intoAug 26, 2026
Merged
Conversation
`Acl::checkUserAccess()` is one switch ending in a deny, so an action id with no case is refused for everyone except an application administrator, who short-circuits at the top. Nothing reports that the id was simply not listed — it looks exactly like a permission somebody has not been granted. Three were in that state, each the only unlisted action in a family whose other members are granted normally, and each with a button its grid renders unconditionally: - PLUGIN_DELETE, beside five plugin actions granted by isConfigGeneral(). - ACCOUNTMGR_HISTORY_RESTORE and ACCOUNTMGR_HISTORY_DELETE, beside the history tab and its search, both granted by isAdminAcc or isMgmAccounts(). So a user holding the profile bit that grants the page could open it, see the actions, and be refused by every one of them. Fail-closed, so these are broken features rather than holes — which is why they had gone unnoticed. They join their siblings. The test is the more useful half: it reads every checkUserAccess(AclActionsInterface::X) in the entry-point tree and asserts Acl has a case for X, so a fourth cannot arrive by being forgotten. Three notification actions — create, edit and delete — stay unlisted, and the test asserts they are still unlisted rather than ignoring them. Adding an arm hands the action to whoever holds some profile bit, and which bit that should be is a decision about the product rather than a defect; the absence has been looked at before, when NOTIFICATION_DELETE was mistakenly described as reachable by any signed-in user. The other direction — an action id no controller checks — is RoutesAreDispatchableTest's business, and this says nothing about it: plenty of ids exist only so permissions can be named. This asks only that what the code checks is what the ACL answers. Checked by removing the PLUGIN_DELETE case again: the test fails, naming it.
blaipr
force-pushed
the
fix/the-acl-answers-the-actions-the-controllers-ask-about
branch
from
August 26, 2026 11:37
03ef93e to
00ebf7c
Compare
blaipr
deleted the
fix/the-acl-answers-the-actions-the-controllers-ask-about
branch
August 26, 2026 11:46
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Acl::checkUserAccess()is one switch ending in a deny, so an action id with no case isrefused for everyone except an application administrator, who short-circuits at the top.
Nothing reports that the id was simply not listed — it looks exactly like a permission
somebody has not been granted.
Three were in that state, each the only unlisted action in a family whose other members
are granted normally, and each with a button its grid renders unconditionally:
search, both granted by isAdminAcc or isMgmAccounts().
So a user holding the profile bit that grants the page could open it, see the actions, and
be refused by every one of them. Fail-closed, so these are broken features rather than
holes — which is why they had gone unnoticed.
They join their siblings. The test is the more useful half: it reads every
checkUserAccess(AclActionsInterface::X) in the entry-point tree and asserts Acl has a case
for X, so a fourth cannot arrive by being forgotten.
Three notification actions — create, edit and delete — stay unlisted, and the test asserts
they are still unlisted rather than ignoring them. Adding an arm hands the action to
whoever holds some profile bit, and which bit that should be is a decision about the
product rather than a defect; the absence has been looked at before, when
NOTIFICATION_DELETE was mistakenly described as reachable by any signed-in user.
The other direction — an action id no controller checks — is RoutesAreDispatchableTest's
business, and this says nothing about it: plenty of ids exist only so permissions can be
named. This asks only that what the code checks is what the ACL answers.
Checked by removing the PLUGIN_DELETE case again: the test fails, naming it.