Skip to content

Fix wildcard unknown-action redirect, isPublic scope leak and hasRole juggling (3.x)#177

Merged
dereuromark merged 1 commit into
cake4from
fix/wildcard-and-scope-cake4
Jun 25, 2026
Merged

Fix wildcard unknown-action redirect, isPublic scope leak and hasRole juggling (3.x)#177
dereuromark merged 1 commit into
cake4from
fix/wildcard-and-scope-cake4

Conversation

@dereuromark

Copy link
Copy Markdown
Owner

Problem

The 3.2.1 release was meant to ship the missing-action wildcard fix (and the isPublic/hasRole fixes) to the CakePHP 4 line, but it was tagged on the cake3 branch (CakePHP 3, cakephp/cakephp ^3.7) instead of cake4. Every other 3.x tag lives on cake4 (CakePHP 4), so 3.2.1 is an anomaly: a CakePHP 4 app cannot even install it. The fixes therefore never reached the 3.x line that users of 3.2.0 actually run.

Reported in issue 173.

What this does

Ports the fixes onto cake4 so the 3.x line reaches parity with the master (5.x) release:

  • Wildcard unknown action: under a * allow rule, an action that does not exist as a controller method is kept in the unauthenticated set, so an unknown action falls through to MissingActionException (404) for guests instead of a login redirect. Explicit denies still win.
  • isPublic scope leak: AclTrait::_isPublic() plugin/prefix guards are now symmetric, so a plugin- or prefix-scoped rule no longer matches a request without one. (AllowTrait already carried the symmetric guard on this branch.)
  • hasRole type juggling: AuthUserTrait::hasRole() compares strictly after string coercion, preserving numeric-string/int equivalence while rejecting 0 == 'admin'-style false positives and auto-int alias keys.

Regression tests added for all three paths.

Gates

phpunit (103 tests), phpstan, phpcs all green locally.

…e leak and hasRole juggling

Port the 3.x (CakePHP 4) line up to parity with the master fix that the
3.2.1 release was meant to ship but landed on the wrong (cake3) branch.

Wildcard fix: a `*` allow rule is expanded to the controller's concrete
method list via get_class_methods() so it can be handed to the
Authentication plugin, which has no wildcard support. An action that does
not exist as a method was dropped from the unauthenticated set, so
unauthenticated users hit the identity check and got redirected to login
instead of receiving the MissingActionException (404) the missing action
should produce. Keep the current request action allowed under a wildcard
rule so unknown actions fall through to MissingActionException, matching
the old AuthComponent behavior. Explicit denies still take precedence.

isPublic scope leak: AclTrait::_isPublic() used asymmetric plugin/prefix
guards that short-circuited when the request had no plugin or prefix, so a
plugin- or prefix-scoped allow rule would match a request without one. Use
symmetric checks so a rule is skipped whenever either side has a scope and
they do not match. (AllowTrait already carries the symmetric guard here.)

hasRole type juggling: AuthUserTrait::hasRole() used a loose in_array()
that matched 0 against any non-numeric string and treated auto-int array
keys as alias matches. Coerce both sides to string and compare strictly
while still treating numeric-string and int as the same role id; only
string array keys count as alias matches. Reject non-scalar inputs early.
@dereuromark dereuromark merged commit 7f1b689 into cake4 Jun 25, 2026
0 of 16 checks passed
@dereuromark dereuromark deleted the fix/wildcard-and-scope-cake4 branch June 25, 2026 12:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant