From d09b113d86bdad488c47b441554232f1f8b32b42 Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Wed, 16 Apr 2025 17:38:06 +0200 Subject: [PATCH 01/16] Add Mage_Csp Module --- .../core/Mage/Csp/Block/Adminhtml/Csp.php | 19 ++ app/code/core/Mage/Csp/Block/Csp.php | 63 ++++ app/code/core/Mage/Csp/Helper/Data.php | 41 +++ app/code/core/Mage/Csp/Model/Config.php | 149 +++++++++ app/code/core/Mage/Csp/etc/config.xml | 60 ++++ app/code/core/Mage/Csp/etc/csp.xml | 8 + app/code/core/Mage/Csp/etc/system.xml | 312 ++++++++++++++++++ .../adminhtml/default/default/layout/csp.xml | 27 ++ .../frontend/base/default/layout/csp.xml | 22 ++ app/etc/modules/Mage_Csp.xml | 26 ++ 10 files changed, 727 insertions(+) create mode 100644 app/code/core/Mage/Csp/Block/Adminhtml/Csp.php create mode 100644 app/code/core/Mage/Csp/Block/Csp.php create mode 100644 app/code/core/Mage/Csp/Helper/Data.php create mode 100644 app/code/core/Mage/Csp/Model/Config.php create mode 100644 app/code/core/Mage/Csp/etc/config.xml create mode 100644 app/code/core/Mage/Csp/etc/csp.xml create mode 100644 app/code/core/Mage/Csp/etc/system.xml create mode 100644 app/design/adminhtml/default/default/layout/csp.xml create mode 100644 app/design/frontend/base/default/layout/csp.xml create mode 100644 app/etc/modules/Mage_Csp.xml diff --git a/app/code/core/Mage/Csp/Block/Adminhtml/Csp.php b/app/code/core/Mage/Csp/Block/Adminhtml/Csp.php new file mode 100644 index 00000000000..ae2eb2109d8 --- /dev/null +++ b/app/code/core/Mage/Csp/Block/Adminhtml/Csp.php @@ -0,0 +1,19 @@ +items[$type] []= $data; + return $this; + } + + /** + * @throws Zend_Controller_Response_Exception + */ + protected function _toHtml(): string + { + $response = $this->getAction()->getResponse(); + if (!$response->canSendHeaders()) { + return ''; + } + + /** + * @var $helper Mage_Csp_Helper_Data + */ + $helper = Mage::helper('csp'); + + if (!Mage::getStoreConfigFlag("$this->section/csp/enabled")) { + return ''; + } + /** + * @var $config Mage_Csp_Model_Config + */ + $config = Mage::getSingleton('csp/config'); + $directives = array_merge_recursive( + $helper->getPolicies($this->section), + $config->getPolicies(), + $this->items + ); + $cspHeader = []; + foreach ($directives as $directive => $value) { + $cspHeader[] = $directive . " " . (is_array($value) ? implode(" ", $value) : strval($value)); + } + + $header = Mage::getStoreConfigFlag("$this->section/csp/report_only") ? + 'Content-Security-Policy-Report-Only' : 'Content-Security-Policy'; + $response->setHeader($header, implode("; ", $cspHeader)); + return ''; + } +} \ No newline at end of file diff --git a/app/code/core/Mage/Csp/Helper/Data.php b/app/code/core/Mage/Csp/Helper/Data.php new file mode 100644 index 00000000000..cda031dac56 --- /dev/null +++ b/app/code/core/Mage/Csp/Helper/Data.php @@ -0,0 +1,41 @@ +setCacheId('config_csp'); + $this->setCacheTags([self::CACHE_TAG]); + $this->setCacheChecksum(null); + + parent::__construct($sourceData); + + $this->_construct(); + } + + /** + * Init configuration for webservices api + * + * @return $this + */ + protected function _construct(): self + { + if (Mage::app()->useCache('config_csp')) { + if ($this->loadCache()) { + return $this; + } + } + + $this->loadString(''); + $config = Mage::getConfig()->loadModulesConfiguration('csp.xml', $this); + + $this->setXml($config->getNode()); + + if (Mage::app()->useCache('config_api')) { + $this->saveCache(); + } + return $this; + } + + /** + * Retrieve all adapters + * + * @return array + */ + public function getPolicies(): array + { + $policies = []; + foreach ($this->getXpath('csp') as $config) { + foreach ($config as $policy => $rules) { + foreach ($rules as $host) { + $policies[$policy][] = (string) $host; + } + } + } + + return $policies; + } + + /** + * Retrieve cache object + * + * @return Zend_Cache_Core + */ + public function getCache() + { + return Mage::app()->getCache(); + } + + /** + * @param string $id + * @return bool + */ + protected function _loadCache($id): bool + { + return (bool)Mage::app()->loadCache($id); + } + + /** + * @param string $data + * @param string $id + * @param array $tags + * @param bool $lifetime + */ + protected function _saveCache($data, $id, $tags = [], $lifetime = false): bool + { + Mage::app()->saveCache($data, $id, $tags, $lifetime); + return true; + } + + /** + * @param string $id + */ + protected function _removeCache($id): void + { + Mage::app()->removeCache($id); + } + + /** + * @param Varien_Simplexml_Config $config + * @param bool $overwrite + * @return $this + */ + public function extend(Varien_Simplexml_Config $config, $overwrite = false): self + { + $config = $config->getNode(); + + if (!$config instanceof Varien_Simplexml_Element) { + return $this; + } + + $this->_extendNode($this->getNode(), $config, $overwrite); + + return $this; + } + + /** + * Custom merging logic that preserves duplicate nodes. + * + * @param Varien_Simplexml_Element $baseNode + * @param Mage_Core_Model_Config_Element $mergeNode + * @param bool $overwrite + */ + protected function _extendNode(Varien_Simplexml_Element $baseNode, Varien_Simplexml_Element $mergeNode, bool $overwrite = false): void + { + foreach ($mergeNode->children() as $key => $child) { + $newChild = $baseNode->addChild($key, (string)$child); + foreach ($child->attributes() as $attrKey => $attrValue) { + $newChild->addAttribute($attrKey, (string)$attrValue); + } + $this->_extendNode($newChild, $child, $overwrite); + } + } +} diff --git a/app/code/core/Mage/Csp/etc/config.xml b/app/code/core/Mage/Csp/etc/config.xml new file mode 100644 index 00000000000..97bf32b0f06 --- /dev/null +++ b/app/code/core/Mage/Csp/etc/config.xml @@ -0,0 +1,60 @@ + + + + + 1.0.0 + + + + + + Mage_Csp_Block + + + + + Mage_Csp_Helper + + + + + Mage_Csp_Model + + + + + + + + csp.xml + + + + + + + + + csp.xml + + + + + + + + 'self' + 'self' 'unsafe-inline' 'unsafe-eval' www.google-analytics.com www.googletagmanager.com stats.g.doubleclick.net www.paypal.com www.paypalobjects.com js.stripe.com connect.facebook.net + 'self' 'unsafe-inline' fonts.googleapis.com maxcdn.bootstrapcdn.com, + 'self' data: www.google-analytics.com stats.g.doubleclick.net www.paypal.com www.paypalobjects.com connect.facebook.net + 'self' www.google-analytics.com www.paypal.com securepayments.paypal.com api.braintreegateway.com js.stripe.com api.stripe.com + 'self' fonts.gstatic.com maxcdn.bootstrapcdn.com + 'self' www.paypal.com payments.amazon.com + 'none' + 'self' + 'self' www.paypal.com securepayments.paypal.com + + + + + diff --git a/app/code/core/Mage/Csp/etc/csp.xml b/app/code/core/Mage/Csp/etc/csp.xml new file mode 100644 index 00000000000..e01fb4ffd8d --- /dev/null +++ b/app/code/core/Mage/Csp/etc/csp.xml @@ -0,0 +1,8 @@ + + + + + *.cloudflare.com + + + \ No newline at end of file diff --git a/app/code/core/Mage/Csp/etc/system.xml b/app/code/core/Mage/Csp/etc/system.xml new file mode 100644 index 00000000000..470eaa04bce --- /dev/null +++ b/app/code/core/Mage/Csp/etc/system.xml @@ -0,0 +1,312 @@ + + + + + + + + + 300 + 1 + 1 + 1 + + + + select + adminhtml/system_config_source_yesno + 10 + 1 + 1 + 1 + + + + + text + 20 + 1 + 1 + 1 + + 1 + + + + + text + 21 + 1 + 1 + 1 + + 1 + + + + + text + 22 + 1 + 1 + 1 + + 1 + + + + + text + 23 + 1 + 1 + 1 + + 1 + + + + + text + 24 + 1 + 1 + 1 + + 1 + + + + + text + 25 + 1 + 1 + 1 + + 1 + + + + + text + 26 + 1 + 1 + 1 + + 1 + + + + + text + 27 + 1 + 1 + 1 + + 1 + + + + + text + 28 + 1 + 1 + 1 + + 1 + + + + + text + 29 + 1 + 1 + 1 + + 1 + + + + + + select + adminhtml/system_config_source_yesno + 100 + 1 + 1 + 1 + + 1 + + + + + + + + + + + + 300 + 1 + 1 + 1 + + + + select + adminhtml/system_config_source_yesno + 10 + 1 + 1 + 1 + + + + + text + 20 + 1 + 1 + 1 + + 1 + + + + + text + 21 + 1 + 1 + 1 + + 1 + + + + + text + 22 + 1 + 1 + 1 + + 1 + + + + + text + 23 + 1 + 1 + 1 + + 1 + + + + + text + 24 + 1 + 1 + 1 + + 1 + + + + + text + 25 + 1 + 1 + 1 + + 1 + + + + + text + 26 + 1 + 1 + 1 + + 1 + + + + + text + 27 + 1 + 1 + 1 + + 1 + + + + + text + 28 + 1 + 1 + 1 + + 1 + + + + + text + 29 + 1 + 1 + 1 + + 1 + + + + + + select + adminhtml/system_config_source_yesno + 100 + 1 + 1 + 1 + + 1 + + + + + + + + \ No newline at end of file diff --git a/app/design/adminhtml/default/default/layout/csp.xml b/app/design/adminhtml/default/default/layout/csp.xml new file mode 100644 index 00000000000..c54876d6cc9 --- /dev/null +++ b/app/design/adminhtml/default/default/layout/csp.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/design/frontend/base/default/layout/csp.xml b/app/design/frontend/base/default/layout/csp.xml new file mode 100644 index 00000000000..c9bd22fa9d8 --- /dev/null +++ b/app/design/frontend/base/default/layout/csp.xml @@ -0,0 +1,22 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/etc/modules/Mage_Csp.xml b/app/etc/modules/Mage_Csp.xml new file mode 100644 index 00000000000..59ff4951231 --- /dev/null +++ b/app/etc/modules/Mage_Csp.xml @@ -0,0 +1,26 @@ + + + + + + true + core + + + + + + \ No newline at end of file From 86a69a44e0407672cae668bbe9c7dd2c9f770b3e Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Wed, 16 Apr 2025 17:50:23 +0200 Subject: [PATCH 02/16] ~ fix style --- app/code/core/Mage/Csp/Block/Adminhtml/Csp.php | 3 ++- app/code/core/Mage/Csp/Block/Csp.php | 10 +++++----- app/code/core/Mage/Csp/Helper/Data.php | 7 ++++--- app/code/core/Mage/Csp/Model/Config.php | 7 ++++--- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/app/code/core/Mage/Csp/Block/Adminhtml/Csp.php b/app/code/core/Mage/Csp/Block/Adminhtml/Csp.php index ae2eb2109d8..02d83e6e284 100644 --- a/app/code/core/Mage/Csp/Block/Adminhtml/Csp.php +++ b/app/code/core/Mage/Csp/Block/Adminhtml/Csp.php @@ -1,4 +1,5 @@ items[$type] []= $data; + $this->items[$type] [] = $data; return $this; } @@ -52,12 +52,12 @@ protected function _toHtml(): string ); $cspHeader = []; foreach ($directives as $directive => $value) { - $cspHeader[] = $directive . " " . (is_array($value) ? implode(" ", $value) : strval($value)); + $cspHeader[] = $directive . ' ' . (is_array($value) ? implode(' ', $value) : strval($value)); } $header = Mage::getStoreConfigFlag("$this->section/csp/report_only") ? 'Content-Security-Policy-Report-Only' : 'Content-Security-Policy'; - $response->setHeader($header, implode("; ", $cspHeader)); + $response->setHeader($header, implode('; ', $cspHeader)); return ''; } -} \ No newline at end of file +} diff --git a/app/code/core/Mage/Csp/Helper/Data.php b/app/code/core/Mage/Csp/Helper/Data.php index cda031dac56..35dbc0e353e 100644 --- a/app/code/core/Mage/Csp/Helper/Data.php +++ b/app/code/core/Mage/Csp/Helper/Data.php @@ -1,4 +1,5 @@ loadCache($id); + return (bool) Mage::app()->loadCache($id); } /** @@ -139,9 +140,9 @@ public function extend(Varien_Simplexml_Config $config, $overwrite = false): sel protected function _extendNode(Varien_Simplexml_Element $baseNode, Varien_Simplexml_Element $mergeNode, bool $overwrite = false): void { foreach ($mergeNode->children() as $key => $child) { - $newChild = $baseNode->addChild($key, (string)$child); + $newChild = $baseNode->addChild($key, (string) $child); foreach ($child->attributes() as $attrKey => $attrValue) { - $newChild->addAttribute($attrKey, (string)$attrValue); + $newChild->addAttribute($attrKey, (string) $attrValue); } $this->_extendNode($newChild, $child, $overwrite); } From 7c5c301038fbad1eb145cc492ba5f231caf50079 Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Wed, 16 Apr 2025 17:55:29 +0200 Subject: [PATCH 03/16] ~ fix style --- app/code/core/Mage/Csp/Block/Csp.php | 6 +++--- app/code/core/Mage/Csp/Model/Config.php | 5 +---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/app/code/core/Mage/Csp/Block/Csp.php b/app/code/core/Mage/Csp/Block/Csp.php index 2c59f8b7470..1ddde465824 100644 --- a/app/code/core/Mage/Csp/Block/Csp.php +++ b/app/code/core/Mage/Csp/Block/Csp.php @@ -34,7 +34,7 @@ protected function _toHtml(): string } /** - * @var $helper Mage_Csp_Helper_Data + * @var Mage_Csp_Helper_Data $helper */ $helper = Mage::helper('csp'); @@ -42,13 +42,13 @@ protected function _toHtml(): string return ''; } /** - * @var $config Mage_Csp_Model_Config + * @var Mage_Csp_Model_Config $config */ $config = Mage::getSingleton('csp/config'); $directives = array_merge_recursive( $helper->getPolicies($this->section), $config->getPolicies(), - $this->items + $this->items, ); $cspHeader = []; foreach ($directives as $directive => $value) { diff --git a/app/code/core/Mage/Csp/Model/Config.php b/app/code/core/Mage/Csp/Model/Config.php index a836462ede0..c9f9b8404c2 100644 --- a/app/code/core/Mage/Csp/Model/Config.php +++ b/app/code/core/Mage/Csp/Model/Config.php @@ -96,7 +96,7 @@ protected function _loadCache($id): bool * @param string $data * @param string $id * @param array $tags - * @param bool $lifetime + * @param false|int $lifetime */ protected function _saveCache($data, $id, $tags = [], $lifetime = false): bool { @@ -133,9 +133,6 @@ public function extend(Varien_Simplexml_Config $config, $overwrite = false): sel /** * Custom merging logic that preserves duplicate nodes. * - * @param Varien_Simplexml_Element $baseNode - * @param Mage_Core_Model_Config_Element $mergeNode - * @param bool $overwrite */ protected function _extendNode(Varien_Simplexml_Element $baseNode, Varien_Simplexml_Element $mergeNode, bool $overwrite = false): void { From 0b04036f36aca68254a0a424ed7162d3aa870b9e Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Wed, 16 Apr 2025 18:01:18 +0200 Subject: [PATCH 04/16] ~ fix style --- app/code/core/Mage/Csp/Block/Adminhtml/Csp.php | 2 +- app/code/core/Mage/Csp/Block/Csp.php | 3 ++- app/code/core/Mage/Csp/Helper/Data.php | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/code/core/Mage/Csp/Block/Adminhtml/Csp.php b/app/code/core/Mage/Csp/Block/Adminhtml/Csp.php index 02d83e6e284..49c9af29d13 100644 --- a/app/code/core/Mage/Csp/Block/Adminhtml/Csp.php +++ b/app/code/core/Mage/Csp/Block/Adminhtml/Csp.php @@ -17,4 +17,4 @@ class Mage_Csp_Block_Adminhtml_Csp extends Mage_Csp_Block_Csp { protected string $section = 'admin'; -} \ No newline at end of file +} diff --git a/app/code/core/Mage/Csp/Block/Csp.php b/app/code/core/Mage/Csp/Block/Csp.php index 1ddde465824..81810ff94ad 100644 --- a/app/code/core/Mage/Csp/Block/Csp.php +++ b/app/code/core/Mage/Csp/Block/Csp.php @@ -1,4 +1,5 @@ $value) { - $cspHeader[] = $directive . ' ' . (is_array($value) ? implode(' ', $value) : strval($value)); + $cspHeader[] = $directive . ' ' . (is_array($value) ? implode(' ', $value) : (string) $value); } $header = Mage::getStoreConfigFlag("$this->section/csp/report_only") ? diff --git a/app/code/core/Mage/Csp/Helper/Data.php b/app/code/core/Mage/Csp/Helper/Data.php index 35dbc0e353e..a85b7f0c5a4 100644 --- a/app/code/core/Mage/Csp/Helper/Data.php +++ b/app/code/core/Mage/Csp/Helper/Data.php @@ -14,7 +14,7 @@ */ class Mage_Csp_Helper_Data extends Mage_Core_Helper_Abstract { - const CONFIG_MAPPING = [ + public const CONFIG_MAPPING = [ 'default-src', 'script-src', 'style-src', From 898029d10a587aedaea03d9b34ada9fcbca681ca Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Thu, 17 Apr 2025 09:19:28 +0200 Subject: [PATCH 05/16] ~ fix phpstan and rector --- .phpstan.dist.baseline.neon | 5 +++++ app/code/core/Mage/Csp/Model/Config.php | 4 ---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.phpstan.dist.baseline.neon b/.phpstan.dist.baseline.neon index 93ccdb6cdc0..80461ba89d4 100644 --- a/.phpstan.dist.baseline.neon +++ b/.phpstan.dist.baseline.neon @@ -8621,3 +8621,8 @@ parameters: identifier: greaterOrEqual.alwaysTrue count: 1 path: tests/unit/Mage/Core/Model/LayoutTest.php + - + message: '#^Return type \(Zend_Cache_Core\) of method Mage_Csp_Model_Config\:\:getCache\(\) should be compatible with return type \(Varien_Simplexml_Config_Cache_Abstract\) of method Varien_Simplexml_Config\:\:getCache\(\)$#' + identifier: method.childReturnType + count: 1 + path: app/code/core/Mage/Csp/Model/Config.php diff --git a/app/code/core/Mage/Csp/Model/Config.php b/app/code/core/Mage/Csp/Model/Config.php index c9f9b8404c2..3e14fcc94ac 100644 --- a/app/code/core/Mage/Csp/Model/Config.php +++ b/app/code/core/Mage/Csp/Model/Config.php @@ -56,8 +56,6 @@ protected function _construct(): self /** * Retrieve all adapters - * - * @return array */ public function getPolicies(): array { @@ -85,7 +83,6 @@ public function getCache() /** * @param string $id - * @return bool */ protected function _loadCache($id): bool { @@ -113,7 +110,6 @@ protected function _removeCache($id): void } /** - * @param Varien_Simplexml_Config $config * @param bool $overwrite * @return $this */ From 9e354c9182aad49fbc5114b8b641812ce93d2fa1 Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Thu, 17 Apr 2025 09:45:21 +0200 Subject: [PATCH 06/16] ~ fix sonar suggestion --- app/code/core/Mage/Csp/Model/Config.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/code/core/Mage/Csp/Model/Config.php b/app/code/core/Mage/Csp/Model/Config.php index 3e14fcc94ac..7e59397b3f8 100644 --- a/app/code/core/Mage/Csp/Model/Config.php +++ b/app/code/core/Mage/Csp/Model/Config.php @@ -37,10 +37,8 @@ public function __construct($sourceData = null) */ protected function _construct(): self { - if (Mage::app()->useCache('config_csp')) { - if ($this->loadCache()) { - return $this; - } + if (Mage::app()->useCache('config_csp') && $this->loadCache()) { + return $this; } $this->loadString(''); From eb59e17ac86c3bab49c6a23b8c53a5e4f802621d Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Sat, 19 Apr 2025 10:06:46 +0200 Subject: [PATCH 07/16] Update app/code/core/Mage/Csp/Block/Csp.php Co-authored-by: Fabrizio Balliano --- app/code/core/Mage/Csp/Block/Csp.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/core/Mage/Csp/Block/Csp.php b/app/code/core/Mage/Csp/Block/Csp.php index 81810ff94ad..a7e29ef03f6 100644 --- a/app/code/core/Mage/Csp/Block/Csp.php +++ b/app/code/core/Mage/Csp/Block/Csp.php @@ -3,14 +3,14 @@ /** * OpenMage * - * This source file is subject to the Academic Free License (AFL 3.0) - * that is bundled with this package in the file LICENSE_AFL.txt. - * It is also available at https://opensource.org/license/afl-3-0-php + * This source file is subject to the Open Software License (OSL 3.0) + * that is bundled with this package in the file LICENSE.txt. + * It is also available at https://opensource.org/license/osl-3-0-php * * @category Mage * @package Mage_Csp * @copyright Copyright (c) 2025 The OpenMage Contributors (https://www.openmage.org) - * @license https://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) + * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ class Mage_Csp_Block_Csp extends Mage_Core_Block_Abstract From 5ee6344cf693d5a5d5bb419d469542378100aa96 Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Sat, 19 Apr 2025 10:07:41 +0200 Subject: [PATCH 08/16] Update app/code/core/Mage/Csp/etc/csp.xml Co-authored-by: Fabrizio Balliano --- app/code/core/Mage/Csp/etc/csp.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/core/Mage/Csp/etc/csp.xml b/app/code/core/Mage/Csp/etc/csp.xml index e01fb4ffd8d..8317c3eeeeb 100644 --- a/app/code/core/Mage/Csp/etc/csp.xml +++ b/app/code/core/Mage/Csp/etc/csp.xml @@ -5,4 +5,4 @@ *.cloudflare.com - \ No newline at end of file + From b55ad09ea5c208bdb523f059cd96f678ee3e3b7f Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Sat, 19 Apr 2025 10:07:52 +0200 Subject: [PATCH 09/16] Update app/design/adminhtml/default/default/layout/csp.xml Co-authored-by: Fabrizio Balliano --- app/design/adminhtml/default/default/layout/csp.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/design/adminhtml/default/default/layout/csp.xml b/app/design/adminhtml/default/default/layout/csp.xml index c54876d6cc9..f98a17a1963 100644 --- a/app/design/adminhtml/default/default/layout/csp.xml +++ b/app/design/adminhtml/default/default/layout/csp.xml @@ -24,4 +24,4 @@ - \ No newline at end of file + From bc287a2d76dd75bc31b585b7b4d12406d4c8fe48 Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Sat, 19 Apr 2025 10:08:04 +0200 Subject: [PATCH 10/16] Update app/design/frontend/base/default/layout/csp.xml Co-authored-by: Fabrizio Balliano --- app/design/frontend/base/default/layout/csp.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/design/frontend/base/default/layout/csp.xml b/app/design/frontend/base/default/layout/csp.xml index c9bd22fa9d8..dbd54d987e3 100644 --- a/app/design/frontend/base/default/layout/csp.xml +++ b/app/design/frontend/base/default/layout/csp.xml @@ -19,4 +19,4 @@ - \ No newline at end of file + From 552ac1cb48eaaf4d13a57f4f38737ebfc266d589 Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Sat, 19 Apr 2025 10:08:18 +0200 Subject: [PATCH 11/16] Update app/etc/modules/Mage_Csp.xml Co-authored-by: Fabrizio Balliano --- app/etc/modules/Mage_Csp.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/etc/modules/Mage_Csp.xml b/app/etc/modules/Mage_Csp.xml index 59ff4951231..156e16d2183 100644 --- a/app/etc/modules/Mage_Csp.xml +++ b/app/etc/modules/Mage_Csp.xml @@ -23,4 +23,4 @@ - \ No newline at end of file + From 394eeecc3264e192e8ea8bb37fac57efefb9a1ab Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Sat, 19 Apr 2025 10:08:30 +0200 Subject: [PATCH 12/16] Update app/code/core/Mage/Csp/Model/Config.php Co-authored-by: Fabrizio Balliano --- app/code/core/Mage/Csp/Model/Config.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/core/Mage/Csp/Model/Config.php b/app/code/core/Mage/Csp/Model/Config.php index 7e59397b3f8..c844eab0568 100644 --- a/app/code/core/Mage/Csp/Model/Config.php +++ b/app/code/core/Mage/Csp/Model/Config.php @@ -126,7 +126,6 @@ public function extend(Varien_Simplexml_Config $config, $overwrite = false): sel /** * Custom merging logic that preserves duplicate nodes. - * */ protected function _extendNode(Varien_Simplexml_Element $baseNode, Varien_Simplexml_Element $mergeNode, bool $overwrite = false): void { From 779216ca6e09e68b190a81173a699fe064f5765c Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Sat, 19 Apr 2025 10:08:43 +0200 Subject: [PATCH 13/16] Update app/code/core/Mage/Csp/Helper/Data.php Co-authored-by: Fabrizio Balliano --- app/code/core/Mage/Csp/Helper/Data.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/core/Mage/Csp/Helper/Data.php b/app/code/core/Mage/Csp/Helper/Data.php index a85b7f0c5a4..b487229c4d3 100644 --- a/app/code/core/Mage/Csp/Helper/Data.php +++ b/app/code/core/Mage/Csp/Helper/Data.php @@ -27,7 +27,6 @@ class Mage_Csp_Helper_Data extends Mage_Core_Helper_Abstract 'form-action', ]; - public function getPolicies(string $section): array { if (!Mage::getStoreConfigFlag("$section/csp/enabled")) { From 6dddd1bf47a1ddb8e1338c991f38c8bf05a41a77 Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Tue, 22 Apr 2025 10:17:53 +0200 Subject: [PATCH 14/16] updated cache-type --- app/code/core/Mage/Csp/Model/Config.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/code/core/Mage/Csp/Model/Config.php b/app/code/core/Mage/Csp/Model/Config.php index c844eab0568..12f4885b25a 100644 --- a/app/code/core/Mage/Csp/Model/Config.php +++ b/app/code/core/Mage/Csp/Model/Config.php @@ -14,6 +14,8 @@ */ class Mage_Csp_Model_Config extends Varien_Simplexml_Config { + public const CACHE_TYPE = 'config'; + public const CACHE_ID = 'config_csp'; public const CACHE_TAG = 'config_csp'; /** @@ -21,7 +23,7 @@ class Mage_Csp_Model_Config extends Varien_Simplexml_Config */ public function __construct($sourceData = null) { - $this->setCacheId('config_csp'); + $this->setCacheId(self::CACHE_ID); $this->setCacheTags([self::CACHE_TAG]); $this->setCacheChecksum(null); @@ -37,7 +39,7 @@ public function __construct($sourceData = null) */ protected function _construct(): self { - if (Mage::app()->useCache('config_csp') && $this->loadCache()) { + if (Mage::app()->useCache(self::CACHE_TYPE) && $this->loadCache()) { return $this; } @@ -46,7 +48,7 @@ protected function _construct(): self $this->setXml($config->getNode()); - if (Mage::app()->useCache('config_api')) { + if (Mage::app()->useCache(self::CACHE_TYPE)) { $this->saveCache(); } return $this; From a2faf6dd590244af5f22e8f613acc0c8de8507ec Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Wed, 23 Apr 2025 09:28:52 +0200 Subject: [PATCH 15/16] ~ apply patch --- .../core/Mage/Csp/Block/Adminhtml/Csp.php | 11 +++-- app/code/core/Mage/Csp/Block/Csp.php | 17 +++---- app/code/core/Mage/Csp/Helper/Data.php | 47 +++++++++++++++---- app/code/core/Mage/Csp/Model/Config.php | 44 +++++++++++++---- 4 files changed, 86 insertions(+), 33 deletions(-) diff --git a/app/code/core/Mage/Csp/Block/Adminhtml/Csp.php b/app/code/core/Mage/Csp/Block/Adminhtml/Csp.php index 49c9af29d13..05c5e9fa84f 100644 --- a/app/code/core/Mage/Csp/Block/Adminhtml/Csp.php +++ b/app/code/core/Mage/Csp/Block/Adminhtml/Csp.php @@ -1,20 +1,21 @@ > */ protected array $items = []; protected string $section = 'system'; public function addItem(string $type, string $data): self { - $this->items[$type] [] = $data; + $this->items[$type][] = $data; return $this; } @@ -34,17 +35,14 @@ protected function _toHtml(): string return ''; } - /** - * @var Mage_Csp_Helper_Data $helper - */ + /** @var Mage_Csp_Helper_Data $helper */ $helper = Mage::helper('csp'); - if (!Mage::getStoreConfigFlag("$this->section/csp/enabled")) { + if (!$helper->isCspEnabled($this->section)) { return ''; } - /** - * @var Mage_Csp_Model_Config $config - */ + + /** @var Mage_Csp_Model_Config $config */ $config = Mage::getSingleton('csp/config'); $directives = array_merge_recursive( $helper->getPolicies($this->section), @@ -56,8 +54,7 @@ protected function _toHtml(): string $cspHeader[] = $directive . ' ' . (is_array($value) ? implode(' ', $value) : (string) $value); } - $header = Mage::getStoreConfigFlag("$this->section/csp/report_only") ? - 'Content-Security-Policy-Report-Only' : 'Content-Security-Policy'; + $header = $helper->getCspHeader($this->section); $response->setHeader($header, implode('; ', $cspHeader)); return ''; } diff --git a/app/code/core/Mage/Csp/Helper/Data.php b/app/code/core/Mage/Csp/Helper/Data.php index b487229c4d3..d7f5a489a90 100644 --- a/app/code/core/Mage/Csp/Helper/Data.php +++ b/app/code/core/Mage/Csp/Helper/Data.php @@ -1,19 +1,24 @@ + */ public function getPolicies(string $section): array { - if (!Mage::getStoreConfigFlag("$section/csp/enabled")) { - return []; - } $result = []; + + if (!$this->isCspEnabled($section)) { + return $result; + } + foreach (self::CONFIG_MAPPING as $key) { - $result [$key] = Mage::getStoreConfig("$section/csp/$key"); + $result[$key] = $this->getCspConfigByKey($section, $key); } return $result; } + + public function isCspEnabled(string $section): bool + { + return Mage::getStoreConfigFlag("$section/csp/enabled"); + } + + public function isCspReportOnly(string $section): bool + { + return Mage::getStoreConfigFlag("$section/csp/report_only"); + } + + public function getCspConfigByKey(string $section, string $key): string + { + return Mage::getStoreConfig("$section/csp/$key"); + } + + public function getCspHeader(string $section): string + { + return $this->isCspReportOnly($section) ? + 'Content-Security-Policy-Report-Only' : 'Content-Security-Policy'; + } } diff --git a/app/code/core/Mage/Csp/Model/Config.php b/app/code/core/Mage/Csp/Model/Config.php index 12f4885b25a..c53576fc250 100644 --- a/app/code/core/Mage/Csp/Model/Config.php +++ b/app/code/core/Mage/Csp/Model/Config.php @@ -1,17 +1,20 @@ useCache(self::CACHE_TYPE) && $this->loadCache()) { + if ($this->hasUseCache() && $this->loadCache()) { return $this; } $this->loadString(''); $config = Mage::getConfig()->loadModulesConfiguration('csp.xml', $this); - $this->setXml($config->getNode()); + $node = $config->getNode(); + if ($node) { + $this->setXml($node); + } - if (Mage::app()->useCache(self::CACHE_TYPE)) { + if ($this->hasUseCache()) { $this->saveCache(); } return $this; @@ -56,11 +62,18 @@ protected function _construct(): self /** * Retrieve all adapters + * @return array> */ public function getPolicies(): array { $policies = []; - foreach ($this->getXpath('csp') as $config) { + + $xpaths = $this->getXpath('csp/policy'); + if (!$xpaths) { + return $policies; + } + + foreach ($xpaths as $config) { foreach ($config as $policy => $rules) { foreach ($rules as $host) { $policies[$policy][] = (string) $host; @@ -92,7 +105,7 @@ protected function _loadCache($id): bool /** * @param string $data * @param string $id - * @param array $tags + * @param array $tags * @param false|int $lifetime */ protected function _saveCache($data, $id, $tags = [], $lifetime = false): bool @@ -121,7 +134,10 @@ public function extend(Varien_Simplexml_Config $config, $overwrite = false): sel return $this; } - $this->_extendNode($this->getNode(), $config, $overwrite); + $node = $this->getNode(); + if ($node) { + $this->_extendNode($node, $config, $overwrite); + } return $this; } @@ -139,4 +155,12 @@ protected function _extendNode(Varien_Simplexml_Element $baseNode, Varien_Simple $this->_extendNode($newChild, $child, $overwrite); } } + + /** + * @return array|false + */ + protected function hasUseCache(): array|false + { + return Mage::app()->useCache(self::CACHE_TYPE); + } } From 5cf956286d74f1f2318b0c43c513ee1c0dc1e9f9 Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Wed, 30 Apr 2025 10:14:25 +0200 Subject: [PATCH 16/16] ~ fix hasUseCache return type --- app/code/core/Mage/Csp/Model/Config.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/core/Mage/Csp/Model/Config.php b/app/code/core/Mage/Csp/Model/Config.php index c53576fc250..546b10cff75 100644 --- a/app/code/core/Mage/Csp/Model/Config.php +++ b/app/code/core/Mage/Csp/Model/Config.php @@ -157,9 +157,9 @@ protected function _extendNode(Varien_Simplexml_Element $baseNode, Varien_Simple } /** - * @return array|false + * @return array|bool|null */ - protected function hasUseCache(): array|false + protected function hasUseCache(): array|bool|null { return Mage::app()->useCache(self::CACHE_TYPE); }