fix: fail closed on permission() exceptions, harden RequestContext flag reset

- AbilityRegistrar: wrap permission_callback in try/catch(Throwable) like
  execute_callback, so a throwing permission() denies (Errors::internal())
  instead of skipping rest_request_after_callbacks and leaving
  RequestContext's flag set for a later request in the same PHP worker.
- RequestContext::recordRoute() now recomputes the flag (and bearer token)
  unconditionally on every matched REST request instead of only setting it
  true for our own route, so a stale true left behind by an earlier request
  is reset by the next non-matching one (fail closed, defense in depth).
- RequestContext::recordRoute() matches the Authorization "Bearer" scheme
  case-insensitively.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
This commit is contained in:
2026-09-25 21:51:41 +02:00
co-authored by Claude Opus 5.5
parent 720d0891c4
commit 1df655a74e
4 changed files with 82 additions and 11 deletions
+7 -1
View File
@@ -60,7 +60,13 @@ final class AbilityRegistrar
return Errors::forbidden('LIT MCP ist nur über den OAuth-geschützten MCP-Server nutzbar.');
}
return $ability->permission(is_array($input) ? $input : []);
try {
return $ability->permission(is_array($input) ? $input : []);
} catch (Throwable $e) {
$message = sprintf('[wp-lit-mcp] %s failed: %s', $ability->name(), $e);
error_log($message); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
return Errors::internal();
}
},
'execute_callback' => static function (mixed $input = null) use ($ability): mixed {
try {