diff --git a/typo3/sysext/core/Classes/Security/Nonce.php b/typo3/sysext/core/Classes/Security/Nonce.php
index 1893231432b66589b325fa206db71616ebb43b17..43f7b4ca203231657288c8f35cc36c19ab2d1c66 100644
--- a/typo3/sysext/core/Classes/Security/Nonce.php
+++ b/typo3/sysext/core/Classes/Security/Nonce.php
@@ -45,7 +45,7 @@ class Nonce implements SigningSecretInterface
             $payload = self::decodeJwt($jwt, self::createSigningKeyFromEncryptionKey(Nonce::class), true);
             return GeneralUtility::makeInstance(
                 self::class,
-                StringUtility::base64urlDecode($payload['nonce'] ?? ''),
+                StringUtility::base64urlDecode($payload['nonce'] ?? '', true),
                 \DateTimeImmutable::createFromFormat(\DateTimeImmutable::RFC3339, $payload['time'] ?? null)
             );
         } catch (\Throwable $t) {
diff --git a/typo3/sysext/core/Classes/Utility/StringUtility.php b/typo3/sysext/core/Classes/Utility/StringUtility.php
index 884805e20f27b23b8287f1b82eed7fc858a8390e..22ce4ee7e4f27ea08882cd6b77ad80b68f12f7a5 100644
--- a/typo3/sysext/core/Classes/Utility/StringUtility.php
+++ b/typo3/sysext/core/Classes/Utility/StringUtility.php
@@ -189,11 +189,12 @@ class StringUtility
      *  + position #63: `_` (underscore) -> `/`
      *
      * @param string $value base64url decoded string
-     * @return string raw value
+     * @param bool $strict enforces to only allow characters contained in the base64(url) alphabet
+     * @return string|false raw value, or `false` if non-base64(url) characters were given in strict mode
      */
-    public static function base64urlDecode(string $value): string
+    public static function base64urlDecode(string $value, bool $strict = false): string|false
     {
-        return base64_decode(strtr($value, ['-' => '+', '_' => '/']));
+        return base64_decode(strtr($value, ['-' => '+', '_' => '/']), $strict);
     }
 
     /**
diff --git a/typo3/sysext/core/Tests/Unit/Utility/StringUtilityTest.php b/typo3/sysext/core/Tests/Unit/Utility/StringUtilityTest.php
index ff7eb41957bb0f9e1d2cdafa07e7129c4bde1654..9eaeedf7d7933f8d3a186ca52950e67d01e309df 100644
--- a/typo3/sysext/core/Tests/Unit/Utility/StringUtilityTest.php
+++ b/typo3/sysext/core/Tests/Unit/Utility/StringUtilityTest.php
@@ -389,6 +389,32 @@ final class StringUtilityTest extends UnitTestCase
         self::assertSame($rawValue, StringUtility::base64urlDecode($encodedValue));
     }
 
+    public static function base64urlStrictDataProvider(): \Generator
+    {
+        yield ['', ''];
+        yield ['YQ', 'a'];
+        yield ['YWE', 'aa'];
+        yield ['YWE-', 'aa>'];
+        yield ['YWE_', 'aa?'];
+        yield ['YWFh', 'aaa'];
+        yield ['YWFhYQ', 'aaaa'];
+        yield ['YWFhYQ!', false];
+        yield ['Y!W!E', false];
+        // `Y W E` is interesting - plain `base64_decode` strips inner spaces
+        yield ['Y W E', 'aa'];
+        yield ["Y\nW\nE", 'aa'];
+        yield ["Y\tW\tE", 'aa'];
+    }
+
+    /**
+     * @test
+     * @dataProvider base64urlStrictDataProvider
+     */
+    public function base64urlStrictDecodeWorks(string $encodedValue, string|bool $expectation): void
+    {
+        self::assertSame($expectation, StringUtility::base64urlDecode($encodedValue, true));
+    }
+
     public static function explodeEscapedDataProvider(): array
     {
         return [