From 85da01dc8fd6706262727e5d45046b90827381f5 Mon Sep 17 00:00:00 2001 From: Oliver Hader <oliver@typo3.org> Date: Sat, 29 Jul 2023 11:06:34 +0200 Subject: [PATCH] [TASK] Use ConsumableNonce instead of blunt Nonce in CSP context To identify whether a nonce values was actually used (consumed), `ConsumableNonce` instances are used, instead of `Nonce` objects. The new `ConsumableNonce` inherits from `ConsumableString`. As a result, the `<f:security.nonce>` view helper would increase the consumption counter. This is important for additional cache handling in the frontend rendering context. Resolves: #101751 Releases: main, 12.4 Change-Id: Iea147b0130e3d350f5913dc75f33af61c18e8af3 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/80235 Tested-by: core-ci <typo3@b13.com> Tested-by: Oliver Hader <oliver.hader@typo3.org> Reviewed-by: Oliver Hader <oliver.hader@typo3.org> --- .../Classes/Controller/MainController.php | 4 +- .../Classes/Modules/Debug/Events.php | 2 +- .../adminpanel/Classes/Utility/HtmlDumper.php | 7 ++-- .../Classes/Utility/ResourceUtility.php | 9 ++-- .../ContentSecurityPolicyHeaders.php | 3 +- typo3/sysext/core/Classes/Core/RequestId.php | 6 +-- .../core/Classes/Domain/ConsumableString.php | 2 +- .../Http/Security/ReferrerEnforcer.php | 4 +- .../core/Classes/Page/AssetRenderer.php | 12 +++--- typo3/sysext/core/Classes/Page/ImportMap.php | 4 +- .../core/Classes/Page/JavaScriptRenderer.php | 6 +-- .../sysext/core/Classes/Page/PageRenderer.php | 10 ++--- .../ContentSecurityPolicy/ConsumableNonce.php | 41 +++++++++++++++++++ .../ContentSecurityPolicy/ModelService.php | 12 ++---- .../Security/ContentSecurityPolicy/Policy.php | 5 +-- .../ContentSecurityPolicy/SourceKeyword.php | 6 +-- .../core/Classes/Utility/DebugUtility.php | 6 --- .../ContentSecurityPolicy/PolicyTest.php | 12 +++--- .../Http/Security/ReferrerEnforcerTest.php | 11 +++-- .../core/Tests/Unit/Page/ImportMapTest.php | 20 ++++----- .../core/Tests/Unit/Page/PageRendererTest.php | 4 +- .../Classes/Utility/DebuggerUtility.php | 2 +- .../ViewHelpers/Security/NonceViewHelper.php | 2 +- .../frontend/Classes/Html/HtmlWorker.php | 7 ++-- .../frontend/Classes/Http/RequestHandler.php | 6 +-- .../ContentSecurityPolicyHeaders.php | 3 +- .../Controller/InstallerController.php | 6 +-- .../Classes/Controller/LayoutController.php | 6 +-- ...ContentSecurityPolicyMutationsProvider.php | 4 +- 29 files changed, 124 insertions(+), 98 deletions(-) create mode 100644 typo3/sysext/core/Classes/Security/ContentSecurityPolicy/ConsumableNonce.php diff --git a/typo3/sysext/adminpanel/Classes/Controller/MainController.php b/typo3/sysext/adminpanel/Classes/Controller/MainController.php index 19dab7f65bf1..e4e62897ef74 100644 --- a/typo3/sysext/adminpanel/Classes/Controller/MainController.php +++ b/typo3/sysext/adminpanel/Classes/Controller/MainController.php @@ -80,7 +80,7 @@ class MainController */ public function render(ServerRequestInterface $request): string { - $resources = ResourceUtility::getResources(['nonce' => $this->requestId->nonce->b64]); + $resources = ResourceUtility::getResources(['nonce' => $this->requestId->nonce]); $view = GeneralUtility::makeInstance(StandaloneView::class); $templateNameAndPath = 'EXT:adminpanel/Resources/Private/Templates/Main.html'; @@ -100,7 +100,7 @@ class MainController $cache = GeneralUtility::makeInstance(CacheManager::class)->getCache('adminpanel_requestcache'); $requestId = $request->getAttribute('adminPanelRequestId'); $data = $cache->get($requestId); - $moduleResources = ResourceUtility::getAdditionalResourcesForModules($this->modules, ['nonce' => $this->requestId->nonce->b64]); + $moduleResources = ResourceUtility::getAdditionalResourcesForModules($this->modules, ['nonce' => $this->requestId->nonce]); $settingsModules = array_filter($this->modules, static function (ModuleInterface $module): bool { return $module instanceof PageSettingsProviderInterface; }); diff --git a/typo3/sysext/adminpanel/Classes/Modules/Debug/Events.php b/typo3/sysext/adminpanel/Classes/Modules/Debug/Events.php index bf5433957218..e64147405caf 100644 --- a/typo3/sysext/adminpanel/Classes/Modules/Debug/Events.php +++ b/typo3/sysext/adminpanel/Classes/Modules/Debug/Events.php @@ -73,7 +73,7 @@ class Events extends AbstractSubModule implements DataProviderInterface $events = $values['events'] ?? null; $dumper = new HtmlDumper(null, null, AbstractDumper::DUMP_LIGHT_ARRAY); - $dumper->setNonce($this->requestId->nonce->b64); + $dumper->setNonce($this->requestId->nonce); $dumper->setTheme('light'); $view->assign('events', $events instanceof Data ? $dumper->dump($events, true) : null); diff --git a/typo3/sysext/adminpanel/Classes/Utility/HtmlDumper.php b/typo3/sysext/adminpanel/Classes/Utility/HtmlDumper.php index ba09d54ef219..4ba873675100 100644 --- a/typo3/sysext/adminpanel/Classes/Utility/HtmlDumper.php +++ b/typo3/sysext/adminpanel/Classes/Utility/HtmlDumper.php @@ -17,6 +17,7 @@ declare(strict_types=1); namespace TYPO3\CMS\Adminpanel\Utility; +use TYPO3\CMS\Core\Security\ContentSecurityPolicy\ConsumableNonce; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Frontend\Html\HtmlWorker; @@ -27,14 +28,14 @@ use TYPO3\CMS\Frontend\Html\HtmlWorker; */ final class HtmlDumper extends \Symfony\Component\VarDumper\Dumper\HtmlDumper { - protected ?string $nonce = null; + protected ?ConsumableNonce $nonce = null; - public function setNonce(string $nonce): void + public function setNonce(ConsumableNonce $nonce): void { $this->nonce = $nonce; $this->dumpSuffix = str_replace( '<script>', - sprintf('<script nonce="%s">', htmlspecialchars($nonce)), + sprintf('<script nonce="%s">', htmlspecialchars($nonce->consume())), $this->dumpSuffix ); } diff --git a/typo3/sysext/adminpanel/Classes/Utility/ResourceUtility.php b/typo3/sysext/adminpanel/Classes/Utility/ResourceUtility.php index 7939f9565795..bab9e998b742 100644 --- a/typo3/sysext/adminpanel/Classes/Utility/ResourceUtility.php +++ b/typo3/sysext/adminpanel/Classes/Utility/ResourceUtility.php @@ -20,6 +20,7 @@ namespace TYPO3\CMS\Adminpanel\Utility; use TYPO3\CMS\Adminpanel\ModuleApi\ModuleInterface; use TYPO3\CMS\Adminpanel\ModuleApi\ResourceProviderInterface; use TYPO3\CMS\Adminpanel\ModuleApi\SubmoduleProviderInterface; +use TYPO3\CMS\Core\Security\ContentSecurityPolicy\ConsumableNonce; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\PathUtility; @@ -30,7 +31,7 @@ class ResourceUtility * one array - returns an array of full html tags * * @param ModuleInterface[] $modules - * @param array<string, string> $attributes + * @param array<string, string|ConsumableNonce> $attributes * @return array{js: string, css: string} */ public static function getAdditionalResourcesForModules(array $modules, array $attributes = []): array @@ -60,7 +61,7 @@ class ResourceUtility /** * Get a css tag for file - with absolute web path resolving * - * @param array<string, string> $attributes + * @param array<string, string|ConsumableNonce> $attributes */ protected static function getCssTag(string $cssFileLocation, array $attributes): string { @@ -78,7 +79,7 @@ class ResourceUtility /** * Get a script tag for JavaScript with absolute paths * - * @param array<string, string> $attributes + * @param array<string, string|ConsumableNonce> $attributes */ protected static function getJsTag(string $jsFileLocation, array $attributes): string { @@ -94,7 +95,7 @@ class ResourceUtility /** * Return a string with tags for main admin panel resources * - * @param array<string, string> $attributes + * @param array<string, string|ConsumableNonce> $attributes */ public static function getResources(array $attributes = []): array { diff --git a/typo3/sysext/backend/Classes/Middleware/ContentSecurityPolicyHeaders.php b/typo3/sysext/backend/Classes/Middleware/ContentSecurityPolicyHeaders.php index b2613b8a1869..5a6a0e9fb594 100644 --- a/typo3/sysext/backend/Classes/Middleware/ContentSecurityPolicyHeaders.php +++ b/typo3/sysext/backend/Classes/Middleware/ContentSecurityPolicyHeaders.php @@ -24,7 +24,6 @@ use Psr\Http\Server\RequestHandlerInterface; use Psr\Log\LoggerInterface; use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface; use TYPO3\CMS\Core\Core\RequestId; -use TYPO3\CMS\Core\Domain\ConsumableString; use TYPO3\CMS\Core\Security\ContentSecurityPolicy\PolicyProvider; use TYPO3\CMS\Core\Security\ContentSecurityPolicy\Scope; use TYPO3\CMS\Core\Security\ContentSecurityPolicy\UriValue; @@ -45,7 +44,7 @@ final class ContentSecurityPolicyHeaders implements MiddlewareInterface public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { - $request = $request->withAttribute('nonce', new ConsumableString($this->requestId->nonce->b64)); + $request = $request->withAttribute('nonce', $this->requestId->nonce); $response = $handler->handle($request); $scope = Scope::backend(); diff --git a/typo3/sysext/core/Classes/Core/RequestId.php b/typo3/sysext/core/Classes/Core/RequestId.php index f7b428b1adde..9401249211df 100644 --- a/typo3/sysext/core/Classes/Core/RequestId.php +++ b/typo3/sysext/core/Classes/Core/RequestId.php @@ -17,7 +17,7 @@ declare(strict_types=1); namespace TYPO3\CMS\Core\Core; -use TYPO3\CMS\Core\Security\Nonce; +use TYPO3\CMS\Core\Security\ContentSecurityPolicy\ConsumableNonce; /** * @internal @@ -27,14 +27,14 @@ final class RequestId public readonly string $long; public readonly string $short; public readonly int $microtime; - public readonly Nonce $nonce; + public readonly ConsumableNonce $nonce; public function __construct() { $this->long = bin2hex(random_bytes(20)); $this->short = substr($this->long, 0, 13); $this->microtime = (int)(microtime(true) * 1000000); - $this->nonce = Nonce::create(); + $this->nonce = new ConsumableNonce(); } public function __toString(): string diff --git a/typo3/sysext/core/Classes/Domain/ConsumableString.php b/typo3/sysext/core/Classes/Domain/ConsumableString.php index 9d83798cecea..219882eaf939 100644 --- a/typo3/sysext/core/Classes/Domain/ConsumableString.php +++ b/typo3/sysext/core/Classes/Domain/ConsumableString.php @@ -22,7 +22,7 @@ namespace TYPO3\CMS\Core\Domain; * This can be used to make decisions during runtime, depending on whether * a provided value actually has been used (e.g. in rendered content). */ -final class ConsumableString implements \Countable, \Stringable +class ConsumableString implements \Countable, \Stringable { /** * @internal use the `consume()` method instead diff --git a/typo3/sysext/core/Classes/Http/Security/ReferrerEnforcer.php b/typo3/sysext/core/Classes/Http/Security/ReferrerEnforcer.php index 556a5bb8c2c9..f7cc0d96faa5 100644 --- a/typo3/sysext/core/Classes/Http/Security/ReferrerEnforcer.php +++ b/typo3/sysext/core/Classes/Http/Security/ReferrerEnforcer.php @@ -19,9 +19,9 @@ namespace TYPO3\CMS\Core\Http\Security; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -use TYPO3\CMS\Core\Domain\ConsumableString; use TYPO3\CMS\Core\Http\HtmlResponse; use TYPO3\CMS\Core\Http\NormalizedParams; +use TYPO3\CMS\Core\Security\ContentSecurityPolicy\ConsumableNonce; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\PathUtility; @@ -85,7 +85,7 @@ class ReferrerEnforcer 'EXT:core/Resources/Public/JavaScript/referrer-refresh.js' ); $attributes = ['src' => $scriptUri]; - if ($nonce instanceof ConsumableString) { + if ($nonce instanceof ConsumableNonce) { $attributes['nonce'] = $nonce->consume(); } // simulating navigate event by clicking anchor link diff --git a/typo3/sysext/core/Classes/Page/AssetRenderer.php b/typo3/sysext/core/Classes/Page/AssetRenderer.php index 529ffdfc484f..5f4567402b2d 100644 --- a/typo3/sysext/core/Classes/Page/AssetRenderer.php +++ b/typo3/sysext/core/Classes/Page/AssetRenderer.php @@ -18,9 +18,9 @@ declare(strict_types=1); namespace TYPO3\CMS\Core\Page; use Psr\EventDispatcher\EventDispatcherInterface; -use TYPO3\CMS\Core\Domain\ConsumableString; use TYPO3\CMS\Core\Page\Event\BeforeJavaScriptsRenderingEvent; use TYPO3\CMS\Core\Page\Event\BeforeStylesheetsRenderingEvent; +use TYPO3\CMS\Core\Security\ContentSecurityPolicy\ConsumableNonce; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\PathUtility; @@ -45,7 +45,7 @@ class AssetRenderer $this->eventDispatcher = $eventDispatcher ?? GeneralUtility::makeInstance(EventDispatcherInterface::class); } - public function renderInlineJavaScript($priority = false, ?ConsumableString $nonce = null): string + public function renderInlineJavaScript($priority = false, ?ConsumableNonce $nonce = null): string { $this->eventDispatcher->dispatch( new BeforeJavaScriptsRenderingEvent($this->assetCollector, true, $priority) @@ -56,7 +56,7 @@ class AssetRenderer return $this->render($assets, $template, $nonce); } - public function renderJavaScript($priority = false, ?ConsumableString $nonce = null): string + public function renderJavaScript($priority = false, ?ConsumableNonce $nonce = null): string { $this->eventDispatcher->dispatch( new BeforeJavaScriptsRenderingEvent($this->assetCollector, false, $priority) @@ -70,7 +70,7 @@ class AssetRenderer return $this->render($assets, $template, $nonce); } - public function renderInlineStyleSheets($priority = false, ?ConsumableString $nonce = null): string + public function renderInlineStyleSheets($priority = false, ?ConsumableNonce $nonce = null): string { $this->eventDispatcher->dispatch( new BeforeStylesheetsRenderingEvent($this->assetCollector, true, $priority) @@ -81,7 +81,7 @@ class AssetRenderer return $this->render($assets, $template, $nonce); } - public function renderStyleSheets(bool $priority = false, string $endingSlash = '', ?ConsumableString $nonce = null): string + public function renderStyleSheets(bool $priority = false, string $endingSlash = '', ?ConsumableNonce $nonce = null): string { $this->eventDispatcher->dispatch( new BeforeStylesheetsRenderingEvent($this->assetCollector, false, $priority) @@ -96,7 +96,7 @@ class AssetRenderer return $this->render($assets, $template, $nonce); } - protected function render(array $assets, string $template, ?ConsumableString $nonce = null): string + protected function render(array $assets, string $template, ?ConsumableNonce $nonce = null): string { $results = []; foreach ($assets as $assetData) { diff --git a/typo3/sysext/core/Classes/Page/ImportMap.php b/typo3/sysext/core/Classes/Page/ImportMap.php index fa4be18f14e3..f87c5e6fad3a 100644 --- a/typo3/sysext/core/Classes/Page/ImportMap.php +++ b/typo3/sysext/core/Classes/Page/ImportMap.php @@ -20,9 +20,9 @@ namespace TYPO3\CMS\Core\Page; use Psr\EventDispatcher\EventDispatcherInterface; use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface; use TYPO3\CMS\Core\Core\Environment; -use TYPO3\CMS\Core\Domain\ConsumableString; use TYPO3\CMS\Core\Package\PackageInterface; use TYPO3\CMS\Core\Page\Event\ResolveJavaScriptImportEvent; +use TYPO3\CMS\Core\Security\ContentSecurityPolicy\ConsumableNonce; use TYPO3\CMS\Core\Utility\ArrayUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\PathUtility; @@ -114,7 +114,7 @@ class ImportMap public function render( string $urlPrefix, - null|string|ConsumableString $nonce + null|string|ConsumableNonce $nonce ): string { if (count($this->extensionsToLoad) === 0 || count($this->getImportMaps()) === 0) { return ''; diff --git a/typo3/sysext/core/Classes/Page/JavaScriptRenderer.php b/typo3/sysext/core/Classes/Page/JavaScriptRenderer.php index 3a2bc28b7be4..225a5990b04f 100644 --- a/typo3/sysext/core/Classes/Page/JavaScriptRenderer.php +++ b/typo3/sysext/core/Classes/Page/JavaScriptRenderer.php @@ -17,7 +17,7 @@ declare(strict_types=1); namespace TYPO3\CMS\Core\Page; -use TYPO3\CMS\Core\Domain\ConsumableString; +use TYPO3\CMS\Core\Security\ContentSecurityPolicy\ConsumableNonce; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\PathUtility; @@ -87,7 +87,7 @@ class JavaScriptRenderer return $this->items->toArray(); } - public function render(null|string|ConsumableString $nonce = null): string + public function render(null|string|ConsumableNonce $nonce = null): string { if ($this->isEmpty()) { return ''; @@ -105,7 +105,7 @@ class JavaScriptRenderer ); } - public function renderImportMap(string $sitePath, null|string|ConsumableString $nonce = null): string + public function renderImportMap(string $sitePath, null|string|ConsumableNonce $nonce = null): string { if (!$this->isEmpty()) { $this->importMap->includeImportsFor('@typo3/core/java-script-item-handler.js'); diff --git a/typo3/sysext/core/Classes/Page/PageRenderer.php b/typo3/sysext/core/Classes/Page/PageRenderer.php index ffdcc908acfb..c5811a34dc13 100644 --- a/typo3/sysext/core/Classes/Page/PageRenderer.php +++ b/typo3/sysext/core/Classes/Page/PageRenderer.php @@ -23,13 +23,13 @@ use TYPO3\CMS\Backend\Routing\Router; use TYPO3\CMS\Backend\Routing\UriBuilder; use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface; use TYPO3\CMS\Core\Core\Environment; -use TYPO3\CMS\Core\Domain\ConsumableString; use TYPO3\CMS\Core\Http\ApplicationType; use TYPO3\CMS\Core\Localization\LanguageServiceFactory; use TYPO3\CMS\Core\Localization\Locale; use TYPO3\CMS\Core\MetaTag\MetaTagManagerRegistry; use TYPO3\CMS\Core\Resource\RelativeCssPathFixer; use TYPO3\CMS\Core\Resource\ResourceCompressor; +use TYPO3\CMS\Core\Security\ContentSecurityPolicy\ConsumableNonce; use TYPO3\CMS\Core\Service\MarkerBasedTemplateService; use TYPO3\CMS\Core\SingletonInterface; use TYPO3\CMS\Core\Type\DocType; @@ -217,7 +217,7 @@ class PageRenderer implements SingletonInterface protected string $endingSlash = ''; protected JavaScriptRenderer $javaScriptRenderer; - protected ?ConsumableString $nonce = null; + protected ?ConsumableNonce $nonce = null; protected DocType $docType = DocType::html5; protected bool $applyNonceHint = false; @@ -254,7 +254,7 @@ class PageRenderer implements SingletonInterface case 'streamFactory': break; case 'nonce': - $this->setNonce(new ConsumableString($value)); + $this->setNonce(new ConsumableNonce($value)); break; case 'metaTagRegistry': $this->metaTagRegistry->updateState($value); @@ -287,7 +287,7 @@ class PageRenderer implements SingletonInterface case 'streamFactory': break; case 'nonce': - if ($value instanceof ConsumableString) { + if ($value instanceof ConsumableNonce) { $state[$var] = $value->value; } break; @@ -560,7 +560,7 @@ class PageRenderer implements SingletonInterface return (string)$this->locale; } - public function setNonce(?ConsumableString $nonce): void + public function setNonce(?ConsumableNonce $nonce): void { $this->nonce = $nonce; } diff --git a/typo3/sysext/core/Classes/Security/ContentSecurityPolicy/ConsumableNonce.php b/typo3/sysext/core/Classes/Security/ContentSecurityPolicy/ConsumableNonce.php new file mode 100644 index 000000000000..2c7af28bf1fa --- /dev/null +++ b/typo3/sysext/core/Classes/Security/ContentSecurityPolicy/ConsumableNonce.php @@ -0,0 +1,41 @@ +<?php + +declare(strict_types=1); + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +namespace TYPO3\CMS\Core\Security\ContentSecurityPolicy; + +use TYPO3\CMS\Core\Domain\ConsumableString; +use TYPO3\CMS\Core\Utility\StringUtility; + +final class ConsumableNonce extends ConsumableString +{ + private const MIN_BYTES = 40; + + /** + * @internal backward compatibility for Nonce::$b64 + * @deprecated will be removed in TYPO3 v13.0, use ConsumableNonce::consume() or ConsumableNonce::$value instead + */ + public readonly string $b64; + + public function __construct(string $nonce = null) + { + if ($nonce === null || strlen($nonce) < self::MIN_BYTES) { + $nonce = random_bytes(self::MIN_BYTES); + } + $this->b64 = StringUtility::base64urlEncode($nonce); + parent::__construct($this->b64); + } +} diff --git a/typo3/sysext/core/Classes/Security/ContentSecurityPolicy/ModelService.php b/typo3/sysext/core/Classes/Security/ContentSecurityPolicy/ModelService.php index f6ae9b825b5a..6b14aaa8320c 100644 --- a/typo3/sysext/core/Classes/Security/ContentSecurityPolicy/ModelService.php +++ b/typo3/sysext/core/Classes/Security/ContentSecurityPolicy/ModelService.php @@ -18,7 +18,6 @@ declare(strict_types=1); namespace TYPO3\CMS\Core\Security\ContentSecurityPolicy; use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface; -use TYPO3\CMS\Core\Security\Nonce; /** * Helpers for working with Content-Security-Policy models. @@ -120,7 +119,7 @@ class ModelService return $serialized; } - public function compileSources(Nonce $nonce, SourceCollection $collection): array + public function compileSources(ConsumableNonce $nonce, SourceCollection $collection): array { $compiled = []; foreach ($collection->sources as $source) { @@ -137,15 +136,12 @@ class ModelService } /** - * @param Nonce|null $nonce used to substitute `SourceKeyword::nonceProxy` items during compilation + * @param ConsumableNonce|null $nonce used to substitute `SourceKeyword::nonceProxy` items during compilation */ - public function serializeSource(SourceInterface $source, Nonce $nonce = null): string + public function serializeSource(SourceInterface $source, ConsumableNonce $nonce = null): string { - if ($source instanceof Nonce) { - return "'nonce-" . $source->b64 . "'"; - } if ($source === SourceKeyword::nonceProxy && $nonce !== null) { - return "'nonce-" . $nonce->b64 . "'"; + return "'nonce-" . $nonce->value . "'"; } if ($source instanceof SourceKeyword) { return "'" . $source->value . "'"; diff --git a/typo3/sysext/core/Classes/Security/ContentSecurityPolicy/Policy.php b/typo3/sysext/core/Classes/Security/ContentSecurityPolicy/Policy.php index eaedc2e7567c..7a3b2a5577a2 100644 --- a/typo3/sysext/core/Classes/Security/ContentSecurityPolicy/Policy.php +++ b/typo3/sysext/core/Classes/Security/ContentSecurityPolicy/Policy.php @@ -18,7 +18,6 @@ declare(strict_types=1); namespace TYPO3\CMS\Core\Security\ContentSecurityPolicy; use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface; -use TYPO3\CMS\Core\Security\Nonce; use TYPO3\CMS\Core\Type\Map; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -230,10 +229,10 @@ class Policy /** * Compiles this policy and returns the serialized representation to be used as HTTP header value. * - * @param Nonce $nonce used to substitute `SourceKeyword::nonceProxy` items during compilation + * @param ConsumableNonce $nonce used to substitute `SourceKeyword::nonceProxy` items during compilation * @param ?FrontendInterface $cache to be used for storing compiled CSP aspects (disabled in install tool) */ - public function compile(Nonce $nonce, ?FrontendInterface $cache = null): string + public function compile(ConsumableNonce $nonce, ?FrontendInterface $cache = null): string { $policyParts = []; $service = GeneralUtility::makeInstance(ModelService::class, $cache); diff --git a/typo3/sysext/core/Classes/Security/ContentSecurityPolicy/SourceKeyword.php b/typo3/sysext/core/Classes/Security/ContentSecurityPolicy/SourceKeyword.php index 2ebc5197ec39..ff5f0e40921e 100644 --- a/typo3/sysext/core/Classes/Security/ContentSecurityPolicy/SourceKeyword.php +++ b/typo3/sysext/core/Classes/Security/ContentSecurityPolicy/SourceKeyword.php @@ -17,8 +17,6 @@ declare(strict_types=1); namespace TYPO3\CMS\Core\Security\ContentSecurityPolicy; -use TYPO3\CMS\Core\Security\Nonce; - /** * Representation of Content-Security-Policy source keywords * see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/Sources#sources @@ -62,9 +60,7 @@ enum SourceKeyword: string implements SourceInterface // apply implications for `'strict-dynamic'` if ($this === self::strictDynamic) { // add nonce-proxy in case it's not defined - if (!$sources->contains(self::nonceProxy) - && !$sources->containsTypes(Nonce::class) - ) { + if (!$sources->contains(self::nonceProxy)) { return $sources->with(self::nonceProxy); } } diff --git a/typo3/sysext/core/Classes/Utility/DebugUtility.php b/typo3/sysext/core/Classes/Utility/DebugUtility.php index 7819dc3fecb1..5d9b4d34c996 100644 --- a/typo3/sysext/core/Classes/Utility/DebugUtility.php +++ b/typo3/sysext/core/Classes/Utility/DebugUtility.php @@ -18,7 +18,6 @@ declare(strict_types=1); namespace TYPO3\CMS\Core\Utility; use TYPO3\CMS\Core\Core\Environment; -use TYPO3\CMS\Core\Core\RequestId; use TYPO3\CMS\Extbase\Utility\DebuggerUtility; /** @@ -156,9 +155,4 @@ class DebugUtility { static::$ansiColorUsage = $ansiColorUsage; } - - protected static function resolveNonceValue(): string - { - return GeneralUtility::makeInstance(RequestId::class)->nonce->b64; - } } diff --git a/typo3/sysext/core/Tests/Functional/Security/ContentSecurityPolicy/PolicyTest.php b/typo3/sysext/core/Tests/Functional/Security/ContentSecurityPolicy/PolicyTest.php index 6524931b4bae..29aa2a40faad 100644 --- a/typo3/sysext/core/Tests/Functional/Security/ContentSecurityPolicy/PolicyTest.php +++ b/typo3/sysext/core/Tests/Functional/Security/ContentSecurityPolicy/PolicyTest.php @@ -17,6 +17,7 @@ declare(strict_types=1); namespace TYPO3\CMS\Core\Tests\Functional\Security\ContentSecurityPolicy; +use TYPO3\CMS\Core\Security\ContentSecurityPolicy\ConsumableNonce; use TYPO3\CMS\Core\Security\ContentSecurityPolicy\Directive; use TYPO3\CMS\Core\Security\ContentSecurityPolicy\HashProxy; use TYPO3\CMS\Core\Security\ContentSecurityPolicy\HashValue; @@ -27,18 +28,17 @@ use TYPO3\CMS\Core\Security\ContentSecurityPolicy\Policy; use TYPO3\CMS\Core\Security\ContentSecurityPolicy\SourceKeyword; use TYPO3\CMS\Core\Security\ContentSecurityPolicy\SourceScheme; use TYPO3\CMS\Core\Security\ContentSecurityPolicy\UriValue; -use TYPO3\CMS\Core\Security\Nonce; use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase; final class PolicyTest extends FunctionalTestCase { - private Nonce $nonce; + private ConsumableNonce $nonce; protected bool $initializeDatabase = false; protected function setUp(): void { parent::setUp(); - $this->nonce = Nonce::create(); + $this->nonce = new ConsumableNonce(); } /** @@ -206,7 +206,7 @@ final class PolicyTest extends FunctionalTestCase public function nonceProxyIsCompiled(): void { $policy = (new Policy(SourceKeyword::self, SourceKeyword::nonceProxy)); - self::assertSame("default-src 'self' 'nonce-{$this->nonce->b64}'", $policy->compile($this->nonce)); + self::assertSame("default-src 'self' 'nonce-{$this->nonce->value}'", $policy->compile($this->nonce)); } /** @@ -220,7 +220,7 @@ final class PolicyTest extends FunctionalTestCase ->extend(Directive::ScriptSrc, SourceKeyword::strictDynamic) ->extend(Directive::StyleSrc, SourceKeyword::strictDynamic); self::assertSame( - "default-src 'self'; script-src 'self' 'strict-dynamic' 'nonce-{$this->nonce->b64}'", + "default-src 'self'; script-src 'self' 'strict-dynamic' 'nonce-{$this->nonce->value}'", $policy->compile($this->nonce) ); } @@ -259,7 +259,7 @@ final class PolicyTest extends FunctionalTestCase ->set(Directive::WorkerSrc, SourceKeyword::self, SourceScheme::blob) ->extend(Directive::FrameSrc, SourceScheme::blob); self::assertSame( - "default-src 'self'; script-src 'self' 'nonce-{$this->nonce->b64}'; " + "default-src 'self'; script-src 'self' 'nonce-{$this->nonce->value}'; " . "style-src 'self' 'unsafe-inline'; style-src-attr 'unsafe-inline'; " . "img-src 'self' data:; worker-src 'self' blob:; frame-src 'self' blob:", $policy->compile($this->nonce) diff --git a/typo3/sysext/core/Tests/Unit/Http/Security/ReferrerEnforcerTest.php b/typo3/sysext/core/Tests/Unit/Http/Security/ReferrerEnforcerTest.php index 0343ddeafd86..e5a527302651 100644 --- a/typo3/sysext/core/Tests/Unit/Http/Security/ReferrerEnforcerTest.php +++ b/typo3/sysext/core/Tests/Unit/Http/Security/ReferrerEnforcerTest.php @@ -18,13 +18,12 @@ declare(strict_types=1); namespace TYPO3\CMS\Core\Tests\Unit\Http\Security; use Psr\Http\Message\ServerRequestInterface; -use TYPO3\CMS\Core\Domain\ConsumableString; use TYPO3\CMS\Core\Http\NormalizedParams; use TYPO3\CMS\Core\Http\Security\InvalidReferrerException; use TYPO3\CMS\Core\Http\Security\MissingReferrerException; use TYPO3\CMS\Core\Http\Security\ReferrerEnforcer; use TYPO3\CMS\Core\Http\Uri; -use TYPO3\CMS\Core\Security\Nonce; +use TYPO3\CMS\Core\Security\ContentSecurityPolicy\ConsumableNonce; use TYPO3\TestingFramework\Core\Unit\UnitTestCase; final class ReferrerEnforcerTest extends UnitTestCase @@ -184,7 +183,7 @@ final class ReferrerEnforcerTest extends UnitTestCase */ public function nonceIsAppliedToResponse(): void { - $nonce = Nonce::create(); + $nonce = new ConsumableNonce(); $subject = $this->buildSubject( 'https://example.org/typo3/login', '', @@ -192,12 +191,12 @@ final class ReferrerEnforcerTest extends UnitTestCase ); $response = $subject->handle(['flags' => ['refresh-always']]); self::assertStringContainsString( - 'nonce="' . htmlspecialchars($nonce->b64) . '">', + 'nonce="' . htmlspecialchars($nonce->value) . '">', (string)$response->getBody() ); } - private function buildSubject(string $requestUri, string $referrer, Nonce $nonce = null): ReferrerEnforcer + private function buildSubject(string $requestUri, string $referrer, ConsumableNonce $nonce = null): ReferrerEnforcer { $requestUriInstance = new Uri($requestUri); $host = sprintf( @@ -214,7 +213,7 @@ final class ReferrerEnforcerTest extends UnitTestCase $request = $this->createMock(ServerRequestInterface::class); $request->method('getAttribute')->willReturnCallback(static fn(string $name): mixed => match ($name) { 'normalizedParams' => $normalizedParams, - 'nonce' => $nonce !== null ? new ConsumableString($nonce->b64) : null, + 'nonce' => $nonce, default => null, }); $request->method('getServerParams')->willReturn(['HTTP_REFERER' => $referrer]); diff --git a/typo3/sysext/core/Tests/Unit/Page/ImportMapTest.php b/typo3/sysext/core/Tests/Unit/Page/ImportMapTest.php index 98f06ed76078..f5f64a267095 100644 --- a/typo3/sysext/core/Tests/Unit/Page/ImportMapTest.php +++ b/typo3/sysext/core/Tests/Unit/Page/ImportMapTest.php @@ -18,11 +18,11 @@ declare(strict_types=1); namespace TYPO3\CMS\Core\Tests\Unit\Page; use TYPO3\CMS\Core\Core\Environment; -use TYPO3\CMS\Core\Domain\ConsumableString; use TYPO3\CMS\Core\Package\MetaData; use TYPO3\CMS\Core\Package\PackageInterface; use TYPO3\CMS\Core\Package\PackageManager; use TYPO3\CMS\Core\Page\ImportMap; +use TYPO3\CMS\Core\Security\ContentSecurityPolicy\ConsumableNonce; use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; use TYPO3\TestingFramework\Core\Unit\UnitTestCase; @@ -69,7 +69,7 @@ final class ImportMapTest extends UnitTestCase $this->packages = ['core']; $importMap = new ImportMap($this->getPackages()); - $output = $importMap->render('/', new ConsumableString('rAnd0m')); + $output = $importMap->render('/', new ConsumableNonce()); self::assertSame('', $output); } @@ -83,7 +83,7 @@ final class ImportMapTest extends UnitTestCase $importMap = new ImportMap($this->getPackages()); $url = $importMap->resolveImport('lit'); - $output = $importMap->render('/', new ConsumableString('rAnd0m')); + $output = $importMap->render('/', new ConsumableNonce()); self::assertSame('', $output); self::assertNull($url); @@ -111,7 +111,7 @@ final class ImportMapTest extends UnitTestCase $importMap = new ImportMap($this->getPackages()); $url = $importMap->resolveImport('lit'); - $output = $importMap->render('/', new ConsumableString('rAnd0m')); + $output = $importMap->render('/', new ConsumableNonce()); self::assertStringStartsWith('Fixtures/ImportMap/core/Resources/Public/JavaScript/Contrib/lit/index.js?bust=', $url); self::assertStringContainsString('"lit/":"/Fixtures/ImportMap/core/Resources/Public/JavaScript/Contrib/lit/"', $output); @@ -128,7 +128,7 @@ final class ImportMapTest extends UnitTestCase $importMap = new ImportMap($this->getPackages()); $importMap->includeImportsFor('@typo3/core/Module1.js'); - $output = $importMap->render('/', new ConsumableString('rAnd0m')); + $output = $importMap->render('/', new ConsumableNonce()); self::assertStringContainsString('"@typo3/core/":"/Fixtures/ImportMap/core/Resources/Public/JavaScript/', $output); self::assertStringContainsString('"@typo3/core/Module1.js":"/Fixtures/ImportMap/core/Resources/Public/JavaScript/Module1.js?bust=', $output); @@ -143,7 +143,7 @@ final class ImportMapTest extends UnitTestCase $importMap = new ImportMap($this->getPackages()); $importMap->includeImportsFor('@typo3/core/Module1.js'); - $output = $importMap->render('/', new ConsumableString('rAnd0m')); + $output = $importMap->render('/', new ConsumableNonce()); self::assertStringContainsString('"@typo3/core/":"/Fixtures/ImportMap/core/Resources/Public/JavaScript/', $output); self::assertStringContainsString('"@typo3/core/Module1.js":"/Fixtures/ImportMap/core/Resources/Public/JavaScript/Module1.js?bust=', $output); @@ -159,7 +159,7 @@ final class ImportMapTest extends UnitTestCase $importMap = new ImportMap($this->getPackages()); $importMap->includeImportsFor('@typo3/package2/File.js'); - $output = $importMap->render('/', new ConsumableString('rAnd0m')); + $output = $importMap->render('/', new ConsumableNonce()); self::assertStringContainsString('"@typo3/package2/File.js":"/Fixtures/ImportMap/package3/Resources/Public/JavaScript/Overrides/Package2/File.js?bust=', $output); self::assertThat( @@ -178,7 +178,7 @@ final class ImportMapTest extends UnitTestCase $this->packages = ['core', 'package2']; $importMap = new ImportMap($this->getPackages()); $importMap->includeImportsFor('@typo3/package2/file.js'); - $output = $importMap->render('/', new ConsumableString('rAnd0m')); + $output = $importMap->render('/', new ConsumableNonce()); self::assertStringContainsString('@typo3/core/', $output); } @@ -191,7 +191,7 @@ final class ImportMapTest extends UnitTestCase $this->packages = ['core', 'package2', 'package4']; $importMap = new ImportMap($this->getPackages()); $importMap->includeImportsFor('@typo3/package2/file.js'); - $output = $importMap->render('/', new ConsumableString('rAnd0m')); + $output = $importMap->render('/', new ConsumableNonce()); self::assertThat( $output, @@ -210,7 +210,7 @@ final class ImportMapTest extends UnitTestCase $importMap = new ImportMap($this->getPackages()); $importMap->includeAllImports(); $importMap->includeImportsFor('@typo3/package2/file.js'); - $output = $importMap->render('/', new ConsumableString('rAnd0m')); + $output = $importMap->render('/', new ConsumableNonce()); self::assertStringContainsString('@typo3/core/', $output); self::assertStringContainsString('@acme/package4/Backend/Helper.js', $output); diff --git a/typo3/sysext/core/Tests/Unit/Page/PageRendererTest.php b/typo3/sysext/core/Tests/Unit/Page/PageRendererTest.php index 6ac8b93cd993..ed7dab010388 100644 --- a/typo3/sysext/core/Tests/Unit/Page/PageRendererTest.php +++ b/typo3/sysext/core/Tests/Unit/Page/PageRendererTest.php @@ -17,11 +17,11 @@ declare(strict_types=1); namespace TYPO3\CMS\Core\Tests\Unit\Page; -use TYPO3\CMS\Core\Domain\ConsumableString; use TYPO3\CMS\Core\Localization\Locale; use TYPO3\CMS\Core\Page\ImportMap; use TYPO3\CMS\Core\Page\ImportMapFactory; use TYPO3\CMS\Core\Page\PageRenderer; +use TYPO3\CMS\Core\Security\ContentSecurityPolicy\ConsumableNonce; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\StringUtility; use TYPO3\TestingFramework\Core\Unit\UnitTestCase; @@ -37,7 +37,7 @@ final class PageRendererTest extends UnitTestCase parent::setUp(); $importMapMock = $this->createMock(ImportMap::class); $importMapMock->method('render') - ->with(self::isType('string'), self::isInstanceOf(ConsumableString::class)) + ->with(self::isType('string'), self::isInstanceOf(ConsumableNonce::class)) ->willReturn(''); $importMapFactoryMock = $this->createMock(ImportMapFactory::class); $importMapFactoryMock->method('create')->willReturn($importMapMock); diff --git a/typo3/sysext/extbase/Classes/Utility/DebuggerUtility.php b/typo3/sysext/extbase/Classes/Utility/DebuggerUtility.php index 6e70b89a1a01..7a9202c332f7 100644 --- a/typo3/sysext/extbase/Classes/Utility/DebuggerUtility.php +++ b/typo3/sysext/extbase/Classes/Utility/DebuggerUtility.php @@ -578,6 +578,6 @@ class DebuggerUtility protected static function resolveNonceValue(): string { - return GeneralUtility::makeInstance(RequestId::class)->nonce->b64; + return GeneralUtility::makeInstance(RequestId::class)->nonce->consume(); } } diff --git a/typo3/sysext/fluid/Classes/ViewHelpers/Security/NonceViewHelper.php b/typo3/sysext/fluid/Classes/ViewHelpers/Security/NonceViewHelper.php index dc9a30491615..5a2daab9bb4c 100644 --- a/typo3/sysext/fluid/Classes/ViewHelpers/Security/NonceViewHelper.php +++ b/typo3/sysext/fluid/Classes/ViewHelpers/Security/NonceViewHelper.php @@ -45,6 +45,6 @@ final class NonceViewHelper extends AbstractViewHelper public function render(): string { - return $this->requestId->nonce->b64; + return $this->requestId->nonce->consume(); } } diff --git a/typo3/sysext/frontend/Classes/Html/HtmlWorker.php b/typo3/sysext/frontend/Classes/Html/HtmlWorker.php index 465112240595..f69be2e1d772 100644 --- a/typo3/sysext/frontend/Classes/Html/HtmlWorker.php +++ b/typo3/sysext/frontend/Classes/Html/HtmlWorker.php @@ -18,6 +18,7 @@ declare(strict_types=1); namespace TYPO3\CMS\Frontend\Html; use Masterminds\HTML5; +use TYPO3\CMS\Core\Security\ContentSecurityPolicy\ConsumableNonce; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Frontend\Typolink\LinkFactory; use TYPO3\CMS\Frontend\Typolink\UnableToLinkException; @@ -72,10 +73,10 @@ class HtmlWorker } /** - * @param string $nonce none value to be added + * @param string|ConsumableNonce $nonce none value to be added * @param string ...$nodeNames element node names to be processed (e.g. `style`) */ - public function addNonceAttribute(string $nonce, string ...$nodeNames): self + public function addNonceAttribute(string|ConsumableNonce $nonce, string ...$nodeNames): self { if ($nodeNames === []) { return $this; @@ -85,7 +86,7 @@ class HtmlWorker $expression = sprintf('//%s[not(@*)]', $nodeName); /** @var \DOMElement $element */ foreach ($xpath->query($expression, $this->mount) as $element) { - $element->setAttribute('nonce', $nonce); + $element->setAttribute('nonce', (string)$nonce); } } return $this; diff --git a/typo3/sysext/frontend/Classes/Http/RequestHandler.php b/typo3/sysext/frontend/Classes/Http/RequestHandler.php index db07b27acced..ec74c9b069b3 100644 --- a/typo3/sysext/frontend/Classes/Http/RequestHandler.php +++ b/typo3/sysext/frontend/Classes/Http/RequestHandler.php @@ -22,7 +22,6 @@ use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; use TYPO3\CMS\Core\Core\Environment; -use TYPO3\CMS\Core\Domain\ConsumableString; use TYPO3\CMS\Core\EventDispatcher\ListenerProvider; use TYPO3\CMS\Core\Http\Response; use TYPO3\CMS\Core\Information\Typo3Information; @@ -32,6 +31,7 @@ use TYPO3\CMS\Core\Page\AssetCollector; use TYPO3\CMS\Core\Page\PageRenderer; use TYPO3\CMS\Core\Resource\Event\GeneratePublicUrlForResourceEvent; use TYPO3\CMS\Core\Resource\Exception; +use TYPO3\CMS\Core\Security\ContentSecurityPolicy\ConsumableNonce; use TYPO3\CMS\Core\Site\Entity\SiteLanguage; use TYPO3\CMS\Core\TimeTracker\TimeTracker; use TYPO3\CMS\Core\Type\DocType; @@ -116,7 +116,7 @@ class RequestHandler implements RequestHandlerInterface if ($controller->isGeneratePage()) { $this->timeTracker->push('Page generation'); - // forward `ConsumableString` containing a nonce to `PageRenderer` + // forward `ConsumableNonce` containing a nonce to `PageRenderer` $nonce = $request->getAttribute('nonce'); $this->getPageRenderer()->setNonce($nonce); @@ -146,7 +146,7 @@ class RequestHandler implements RequestHandlerInterface // already - this is due to the fact that the `PageRenderer` state has been serialized // before and note executed via `$pageRenderer->render()` and did not consume any nonce values // (see serialization in `generatePageContent()`). - if ($nonce instanceof ConsumableString && (count($nonce) > 0 || $controller->isINTincScript())) { + if ($nonce instanceof ConsumableNonce && (count($nonce) > 0 || $controller->isINTincScript())) { // nonce was consumed $controller->config['INTincScript'][] = [ 'target' => NonceValueSubstitution::class . '->substituteNonce', diff --git a/typo3/sysext/frontend/Classes/Middleware/ContentSecurityPolicyHeaders.php b/typo3/sysext/frontend/Classes/Middleware/ContentSecurityPolicyHeaders.php index 6a953385f9f4..ccd7c51059a1 100644 --- a/typo3/sysext/frontend/Classes/Middleware/ContentSecurityPolicyHeaders.php +++ b/typo3/sysext/frontend/Classes/Middleware/ContentSecurityPolicyHeaders.php @@ -25,7 +25,6 @@ use Psr\Log\LoggerInterface; use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface; use TYPO3\CMS\Core\Configuration\Features; use TYPO3\CMS\Core\Core\RequestId; -use TYPO3\CMS\Core\Domain\ConsumableString; use TYPO3\CMS\Core\Security\ContentSecurityPolicy\PolicyProvider; use TYPO3\CMS\Core\Security\ContentSecurityPolicy\Scope; use TYPO3\CMS\Core\Security\ContentSecurityPolicy\UriValue; @@ -52,7 +51,7 @@ final class ContentSecurityPolicyHeaders implements MiddlewareInterface return $handler->handle($request); } // make sure, the nonce value is set before processing the remaining middlewares - $request = $request->withAttribute('nonce', new ConsumableString($this->requestId->nonce->b64)); + $request = $request->withAttribute('nonce', $this->requestId->nonce); $response = $handler->handle($request); $site = $request->getAttribute('site'); diff --git a/typo3/sysext/install/Classes/Controller/InstallerController.php b/typo3/sysext/install/Classes/Controller/InstallerController.php index b238136acf41..b8d3fa1abea7 100644 --- a/typo3/sysext/install/Classes/Controller/InstallerController.php +++ b/typo3/sysext/install/Classes/Controller/InstallerController.php @@ -38,7 +38,7 @@ use TYPO3\CMS\Core\Messaging\FlashMessageQueue; use TYPO3\CMS\Core\Middleware\VerifyHostHeader; use TYPO3\CMS\Core\Package\FailsafePackageManager; use TYPO3\CMS\Core\Page\ImportMap; -use TYPO3\CMS\Core\Security\Nonce; +use TYPO3\CMS\Core\Security\ContentSecurityPolicy\ConsumableNonce; use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\View\FluidViewAdapter; @@ -102,8 +102,8 @@ final class InstallerController $view = $this->initializeView(); $view->assign('bust', $bust); $view->assign('initModule', $initModule); - $nonce = Nonce::create(); - $view->assign('importmap', $importMap->render($sitePath, $nonce->b64)); + $nonce = new ConsumableNonce(); + $view->assign('importmap', $importMap->render($sitePath, $nonce)); return new HtmlResponse( $view->render('Installer/Init'), diff --git a/typo3/sysext/install/Classes/Controller/LayoutController.php b/typo3/sysext/install/Classes/Controller/LayoutController.php index f766479a6b17..2951e0063fe2 100644 --- a/typo3/sysext/install/Classes/Controller/LayoutController.php +++ b/typo3/sysext/install/Classes/Controller/LayoutController.php @@ -27,7 +27,7 @@ use TYPO3\CMS\Core\Http\JsonResponse; use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Package\FailsafePackageManager; use TYPO3\CMS\Core\Page\ImportMap; -use TYPO3\CMS\Core\Security\Nonce; +use TYPO3\CMS\Core\Security\ContentSecurityPolicy\ConsumableNonce; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Install\Service\Exception\ConfigurationChangedException; use TYPO3\CMS\Install\Service\Exception\SilentConfigurationUpgradeReadonlyException; @@ -74,13 +74,13 @@ class LayoutController extends AbstractController $initModule = $sitePath . $importMap->resolveImport('@typo3/install/init-install.js'); $view = $this->initializeView($request); - $nonce = Nonce::create(); + $nonce = new ConsumableNonce(); $view->assignMultiple([ // time is used as cache bust for js and css resources 'bust' => $bust, 'siteName' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'], 'initModule' => $initModule, - 'importmap' => $importMap->render($sitePath, $nonce->b64), + 'importmap' => $importMap->render($sitePath, $nonce), ]); return new HtmlResponse( $view->render('Layout/Init'), diff --git a/typo3/sysext/lowlevel/Classes/ConfigurationModuleProvider/ContentSecurityPolicyMutationsProvider.php b/typo3/sysext/lowlevel/Classes/ConfigurationModuleProvider/ContentSecurityPolicyMutationsProvider.php index b65eb0495617..19897d88511c 100644 --- a/typo3/sysext/lowlevel/Classes/ConfigurationModuleProvider/ContentSecurityPolicyMutationsProvider.php +++ b/typo3/sysext/lowlevel/Classes/ConfigurationModuleProvider/ContentSecurityPolicyMutationsProvider.php @@ -17,6 +17,7 @@ declare(strict_types=1); namespace TYPO3\CMS\Lowlevel\ConfigurationModuleProvider; +use TYPO3\CMS\Core\Security\ContentSecurityPolicy\ConsumableNonce; use TYPO3\CMS\Core\Security\ContentSecurityPolicy\ModelService; use TYPO3\CMS\Core\Security\ContentSecurityPolicy\MutationCollection; use TYPO3\CMS\Core\Security\ContentSecurityPolicy\MutationOrigin; @@ -25,7 +26,6 @@ use TYPO3\CMS\Core\Security\ContentSecurityPolicy\Policy; use TYPO3\CMS\Core\Security\ContentSecurityPolicy\Scope; use TYPO3\CMS\Core\Security\ContentSecurityPolicy\SourceInterface; use TYPO3\CMS\Core\Security\ContentSecurityPolicy\SourceValueInterface; -use TYPO3\CMS\Core\Security\Nonce; use TYPO3\CMS\Core\Type\Map; use TYPO3\CMS\Core\Utility\ArrayUtility; @@ -38,7 +38,7 @@ class ContentSecurityPolicyMutationsProvider extends AbstractProvider public function getConfiguration(): array { - $nonce = Nonce::create(); + $nonce = new ConsumableNonce(); $data = []; /** * @var Scope $scope -- GitLab