Problem/Motivation
Contrib modules might want to throw an AccessDeniedException to deny access to certain pages depending on certain conditions. This exception frequently takes place in situations where no route has been established (e.g. in a kernel event subscriber etc.). Right now, this leads to an error message "Call to a member function hasRequirement() on null" due to the following code in core/lib/Drupal/Core/EventSubscriber/CsrfExceptionSubscriber.php, on403 method:
if (!$route->hasRequirement('_csrf_token') || empty($route->getOption('_csrf_confirm_form_route'))) {
return;
}
The solution is as simple as this little change:
if (is_null($route) || !$route->hasRequirement('_csrf_token') || empty($route->getOption('_csrf_confirm_form_route'))) {
return;
}
See also: https://www.drupal.org/project/drupal/issues/3511584
Over at this issue, the "ban" module is affected, but the ban module is about to be moved out of core and this feature request is IMHO absolut valid independent of this module. That's why I'm filing a new issue here to make it independent of the ban module and to specifiy that it's not strictly speaking a bug in core, because there are probably no test cases in core after the ban module is removed.
Steps to reproduce
I'm attaching my test module here again. To reproduce install the module "crash403" attached and call an URL on your Drupal site that ends with "/crash". I'll see if I can create a normal test case.
Proposed resolution
See above. Just add "is_null($route) ||"
Remaining tasks
User interface changes
None
Introduced terminology
None
API changes
None
Data model changes
None
Release notes snippet
Don't know if necessary. If at all perhaps the fact that you can now throw AccessDeniedException everywhere. But that's IMHO the expectation anyway.
| Comment | File | Size | Author |
|---|
Issue fork drupal-3566351
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
quietone commentedIn Drupal core changes are made on on 11.x (our main development branch) first, and are then back ported as needed according to the Core change policies. Thanks.
Comment #3
sourav_paulchecking...
Comment #4
sourav_paul@rgpublic I tested the proposed change in CsrfExceptionSubscriber and it results in an infinite redirect / exception loop, eventually causing a fatal “allowed memory size exhausted” error.
Flow observed:
This is not a memory leak but an unbounded 403 → redirect → 403 loop during exception handling.
The implementation needs a guard (e.g. prevent redirecting to the same route, avoid redirecting to routes with _csrf_token, or mark the request as already handled). Without this, redirecting from an exception subscriber is unsafe.
Got this issue after applying changes:

Comment #5
rgpublicThank you @sourav_paul for looking into this issue. Really appreciate it. You are right of course. In certain circumstances this can lead to an endless loop. I'd see that in the responsibility of the triggering module though. I've added a:
To prevent that the subrequest that fetches the 403 retriggers the original condition. I've added the corrected module.
Now, how do we go from here? I guess we'd need a test, right? I've no experience with that but I might try my luck if you are saying that's what we need next.
Comment #6
sourav_paulHi @rgpublic your attached zip file is empty, can you provide the valid module?
Comment #7
rgpublic@sourav_paul: D'oh. My bad. I've attached the valid module now. Sorry for the completely unnecessary roundtrip. My fault :-(
Comment #9
sourav_paulThanks @rgpublic, I've tested the fix to get AccessDeniedHttpException on a non-existing route, triggered my logic onKernelRequest event, it fixes the WSOD issue, hence moving it to NR.
Attaching test ss with it:
Before:

After:

Thanks...
Comment #10
sourav_paulComment #11
smustgrave commentedWill need test coverage
Comment #13
sourav_paulComment #14
smustgrave commentedComment #15
sourav_paulComment #16
smustgrave commentedWill leave for others then no one picks up after a few months I’ll relook. Thanks
Comment #17
smustgrave commentedComment #18
sourav_paulComment #19
smustgrave commentedFeedback appears to be addressed on this one.
Comment #20
alexpottComment #24
alexpottCommitted and pushed 051f4387948 to main and d40e456dd0f to 11.x and 841cd847977 to 11.3.x. Thanks!
Comment #27
scott_euser commentedAdding related issue that this resolved, thanks!