diff --git a/Plugin/Model/Policy/Renderer/CspHeaderSplitter.php b/Plugin/Model/Policy/Renderer/CspHeaderSplitter.php index b46b763..2b027b7 100644 --- a/Plugin/Model/Policy/Renderer/CspHeaderSplitter.php +++ b/Plugin/Model/Policy/Renderer/CspHeaderSplitter.php @@ -10,7 +10,7 @@ use Laminas\Http\Header\HeaderInterface; use Laminas\Loader\PluginClassLoader; use Magento\Csp\Api\Data\PolicyInterface; -use Magento\Csp\Model\Policy\Renderer\SimplePolicyHeaderRenderer; +use Magento\Csp\Model\CspRenderer; use Magento\Framework\App\Response\HttpInterface as HttpResponse; use Psr\Log\LoggerInterface; @@ -37,26 +37,28 @@ public function __construct( * @param null $result */ public function afterRender( - SimplePolicyHeaderRenderer $subject, + CspRenderer $subject, $result, - PolicyInterface $policy, HttpResponse $response ): void { $headerName = $this->getHeaderName($response); - /** @var HeaderInterface $header */ $header = $response->getHeader($headerName); - $policyValue = $header->getFieldValue(); + if (!$header instanceof HeaderInterface) { + return; + } + + $headerValue = $header->getFieldValue(); $isHeaderSplittingEnabled = $this->config->isHeaderSplittingEnabled(); $maxHeaderSize = $this->config->getMaxHeaderSize(); - $currentHeaderSize = strlen($policyValue); + $currentHeaderSize = strlen($headerValue); if ($isHeaderSplittingEnabled) { $this->registerCspHeaderPlugins($response); - $this->splitUpCspHeaders($response, $policyValue); + $this->splitUpCspHeaders($response, $headerName, $headerValue); } else { if ($maxHeaderSize >= $currentHeaderSize) { - $response->setHeader($headerName, $policyValue, true); + $response->setHeader($headerName, $headerValue, true); } else { $this->logger->error( sprintf( @@ -87,33 +89,41 @@ private function registerCspHeaderPlugins(HttpResponse $response): void /** * Make sure that the CSP headers are handled as several headers ("multi-header") */ - private function splitUpCspHeaders(HttpResponse $response, string $policyValue): void + private function splitUpCspHeaders(HttpResponse $response, string $headerName, string $headerValue): void { - $headerName = $this->getHeaderName($response); + $maxHeaderSize = $this->config->getMaxHeaderSize(); - if (!$headerName) { - return; - } + $headerParts[$i = 0] = ''; - $maxHeaderSize = $this->config->getMaxHeaderSize(); - $newHeaderSize = strlen($policyValue); + $policyValues = explode(';', $headerValue); + foreach ($policyValues as $policyValue) { + $policyValue = trim($policyValue) . ';'; + $newHeaderSize = strlen($headerParts[$i]) + strlen($policyValue); - if ($newHeaderSize <= $maxHeaderSize) { - $this->contentHeaders[] = $policyValue; - } else { - $this->logger->error( - sprintf( - 'Unable to set the CSP header. The header size of %d bytes exceeds the '. - 'maximum size of %d bytes.', - $newHeaderSize, - $maxHeaderSize - ) - ); + if ($newHeaderSize <= $maxHeaderSize) { + $headerParts[$i] .= $policyValue; + + continue; + } + + $headerParts[++$i] = $policyValue; + $headerSize = strlen($policyValue); + if ($headerSize > $maxHeaderSize) { + $this->logger->error( + sprintf( + 'Unable to set the CSP header. The header size of %d bytes exceeds the '. + 'maximum size of %d bytes.', + $headerSize, + $maxHeaderSize + ) + ); + + return; + } } - foreach ($this->contentHeaders as $i => $headerPart) { - $isFirstEntry = ($i === 0); - $response->setHeader($headerName, $headerPart.';', $isFirstEntry); + foreach ($headerParts as $i => $headerPart) { + $response->setHeader($headerName, $headerPart.';', $i === 0); } } diff --git a/etc/di.xml b/etc/di.xml index aa6768c..a42a611 100644 --- a/etc/di.xml +++ b/etc/di.xml @@ -3,7 +3,7 @@ xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> - +