Skip to content
This repository was archived by the owner on May 29, 2026. It is now read-only.

Commit 89380de

Browse files
committed
fix(security): PermissionHandler — fail CLOSED on custom-scope dispatch error
`dispatchCustomScopeEvaluation()` caught listener exceptions, logged them, and returned `null` — letting the caller fall through to the standard rule chain. For canonical verbs that's safe (chain decides), but custom verbs (ZGW `besluit_nemen` etc.) explicitly delegate the verdict to the listener; the chain has no opinion and "deny by default" was the *intent*. The risk: when a listener has previously voted ALLOW for a verb but the dispatcher itself throws, the cleared verdict + chain-fallback can silently open access. Treat the dispatcher exception as a deny vote (`return false`). A genuinely down listener is a security event — let it surface as an explicit denial rather than a no-op. Listener `deny()` votes that land before the throw still propagate via the existing `hasVerdict()` path. Refs: #1419 review (concern 6) — discussion_r3187494479
1 parent c10828b commit 89380de

1 file changed

Lines changed: 12 additions & 2 deletions

File tree

lib/Service/Object/PermissionHandler.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -506,16 +506,26 @@ private function dispatchCustomScopeEvaluation(
506506
try {
507507
$this->eventDispatcher->dispatchTyped($event);
508508
} catch (Exception $e) {
509+
// SECURITY: fail CLOSED. A listener exception means the app
510+
// that owns the verdict for this verb is unavailable — for
511+
// verbs the standard rule chain has no opinion on (the
512+
// common case for custom verbs like ZGW `besluit_nemen`),
513+
// falling through to "deny by default" is acceptable, but
514+
// for verbs where a listener has previously voted ALLOW,
515+
// returning null lets the standard chain re-decide and
516+
// potentially open access. Treat the dispatcher exception
517+
// itself as a deny vote so a crashed listener cannot
518+
// upgrade-to-allow.
509519
$this->logger->warning(
510-
message: '[PermissionHandler] CustomScopeEvaluatingEvent dispatch failed',
520+
message: '[PermissionHandler] CustomScopeEvaluatingEvent dispatch failed — denying',
511521
context: [
512522
'file' => __FILE__,
513523
'line' => __LINE__,
514524
'action' => $action,
515525
'error' => $e->getMessage(),
516526
]
517527
);
518-
return null;
528+
return false;
519529
}
520530

521531
if ($event->hasVerdict() === false) {

0 commit comments

Comments
 (0)