diff --git a/CHANGELOG.md b/CHANGELOG.md index 35048103..9e067f6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # REDAXO consent_manager - Changelog +## Version 5.3.3 - 29.01.2026 + +- **Fix:** JSON Parsing Fehler im Frontend behoben (`double-escaping` von HTML-Attributen entfernt), was zu Fehlern beim Laden der Cookie-Gruppen führte (`safeJSONParse failed`). + +- **Fix:** Fehler beim Laden von Framework-Templates behoben (`Call to undefined method rex_fragment::subparse()`). +- **Security:** XSS-Schwachstelle in `consent_manager_outputjs` behoben (Input-Sanitizing für `cid` und `v` Parameter). +- **Security:** Schutz vor Host-Header Injection im Frontend-Output. +- **Fix:** JavaScript Syntax-Fehler durch verbessertes Template-Escaping behoben (`json_encode` statt string replace). +- **Fix:** Google Consent Mode v2 Script auf ES5 Syntax aktualisiert (SyntaxError Fix für ältere Umgebungen). + ## Version 5.3.0 - 28.01.2026 **🚀 Release-Highlights:** diff --git a/Namespace-Guide.md b/Namespace-Guide.md deleted file mode 100644 index c0190b33..00000000 --- a/Namespace-Guide.md +++ /dev/null @@ -1,100 +0,0 @@ -# Namespace-Guide für consent_manager 5.0 - -Ab Version 5.0 verwendet der Consent Manager den Namespace `FriendsOfRedaxo\ConsentManager`. - -## Übersicht der Klassen-Änderungen - -| Alter Klassenname | Neuer Klassenname | -|-------------------|-------------------| -| `consent_manager_frontend` | `FriendsOfRedaxo\ConsentManager\Frontend` | -| `consent_manager_util` | `FriendsOfRedaxo\ConsentManager\Utility` | -| `consent_manager_config` | `FriendsOfRedaxo\ConsentManager\Config` | -| `consent_manager_cache` | `FriendsOfRedaxo\ConsentManager\Cache` | -| `consent_manager_clang` | `FriendsOfRedaxo\ConsentManager\CLang` | -| `consent_manager_inline` | `FriendsOfRedaxo\ConsentManager\InlineConsent` | -| `consent_manager_theme` | `FriendsOfRedaxo\ConsentManager\Theme` | -| `consent_manager_google_consent_mode` | `FriendsOfRedaxo\ConsentManager\GoogleConsentMode` | -| `consent_manager_json_setup` | `FriendsOfRedaxo\ConsentManager\JsonSetup` | -| `consent_manager_oembed_parser` | `FriendsOfRedaxo\ConsentManager\OEmbedParser` | -| `consent_manager_thumbnail_cache` | `FriendsOfRedaxo\ConsentManager\ThumbnailCache` | -| `consent_manager_rex_form` | `FriendsOfRedaxo\ConsentManager\RexFormSupport` | -| `consent_manager_rex_list` | `FriendsOfRedaxo\ConsentManager\RexListSupport` | -| `rex_api_consent_manager` | `FriendsOfRedaxo\ConsentManager\Api\ConsentManager` | -| `rex_api_consent_manager_inline_log` | `FriendsOfRedaxo\ConsentManager\Api\InlineLog` | -| `rex_cronjob_log_delete` | `FriendsOfRedaxo\ConsentManager\Cronjob\LogDelete` | -| `rex_cronjob_consent_manager_thumbnail_cleanup` | `FriendsOfRedaxo\ConsentManager\Cronjob\ThumbnailCleanup` | -| `rex_consent_manager_thumbnail_mediamanager` | `FriendsOfRedaxo\ConsentManager\ThumbnailMediaManager` | -| `rex_consent_manager_command_log_delete` | `FriendsOfRedaxo\ConsentManager\Command\LogDelete` | - -## Migration deines Codes - -### Vorher (alt) - -```php -$frontend = new consent_manager_frontend(0); -$frontend->showBox(); - -consent_manager_util::hostname(); -``` - -### Nachher (neu) - -```php -use FriendsOfRedaxo\ConsentManager\Frontend; -use FriendsOfRedaxo\ConsentManager\Utility; - -$frontend = new Frontend(0); -$frontend->showBox(); - -Utility::hostname(); -``` - -### Alternative mit vollqualifiziertem Namen - -```php -$frontend = new \FriendsOfRedaxo\ConsentManager\Frontend(0); -\FriendsOfRedaxo\ConsentManager\Utility::hostname(); -``` - -## Übergangszeit - -Die alten Klassennamen funktionieren weiterhin, sind aber als `@deprecated` markiert. Du bekommst also keine Fehler, solltest aber deinen Code bei Gelegenheit anpassen. - -Die Deprecated-Klassen findest du in `lib/deprecated/` – sie leiten einfach auf die neuen Namespace-Klassen weiter. - -## doConsent() Funktion - -Die Shorthand-Funktion `doConsent()` bleibt unverändert verfügbar: - -```php -// Das funktioniert weiterhin -echo doConsent('youtube', ''); -``` - -Alternativ mit der neuen Klasse: - -```php -use FriendsOfRedaxo\ConsentManager\InlineConsent; - -echo InlineConsent::doConsent('youtube', ''); -``` - -## Fragmente - -Die Fragmente wurden in ein Unterverzeichnis verschoben: - -| Vorher | Nachher | -|--------|---------| -| `consent_manager_box.php` | `ConsentManager/box.php` | -| `consent_manager_consent_box.php` | `ConsentManager/consent_box.php` | - -```php -// Neu -$fragment = new rex_fragment(); -$fragment->setVar('domain', $domain); -echo $fragment->parse('ConsentManager/box.php'); -``` - -## Fragen? - -Bei Fragen oder Problemen: [GitHub Issues](https://github.com/FriendsOfREDAXO/consent_manager/issues) oder [REDAXO Slack](https://redaxo.org/slack/) diff --git a/assets/consent_cookie_helper.js b/assets/consent_cookie_helper.js new file mode 100644 index 00000000..e69de29b diff --git a/fragments/ConsentManager/box.php b/fragments/ConsentManager/box.php index 29b4811b..940126b2 100644 --- a/fragments/ConsentManager/box.php +++ b/fragments/ConsentManager/box.php @@ -22,7 +22,7 @@ // Check for CSS Framework Mode $cssFrameworkMode = rex_addon::get('consent_manager')->getConfig('css_framework_mode'); if ($cssFrameworkMode) { - echo $this->subparse('ConsentManager/box_' . $cssFrameworkMode . '.php'); + echo $this->parse('ConsentManager/box_' . $cssFrameworkMode . '.php'); return; } diff --git a/lib/Frontend.php b/lib/Frontend.php index 915835ce..ad5dfb53 100644 --- a/lib/Frontend.php +++ b/lib/Frontend.php @@ -259,17 +259,20 @@ public function outputJavascript(): never /** @phpstan-ignore-next-line */ $boxtemplate = sprogdown($boxtemplate, $clang); } - $boxtemplate = str_replace("'", "\\'", $boxtemplate); $boxtemplate = str_replace("\r", '', $boxtemplate); $boxtemplate = str_replace("\n", ' ', $boxtemplate); echo '/* --- Parameters --- */' . PHP_EOL; + // Sanitize input parameters to prevent XSS + $cacheLogId = preg_replace('/[^a-zA-Z0-9_\-]/', '', rex_request::get('cid', 'string', '')); + $version = preg_replace('/[^0-9.]/', '', rex_request::get('v', 'string', '')); + $consent_manager_parameters = [ 'initially_hidden' => 'true' === rex_request::get('i', 'string', 'false'), 'domain' => Utility::hostname(), 'consentid' => uniqid('', true), - 'cachelogid' => rex_request::get('cid', 'string', ''), - 'version' => rex_request::get('v', 'string', ''), + 'cachelogid' => $cacheLogId, + 'version' => $version, 'fe_controller' => rex_url::frontend(), 'forcereload' => rex_request::get('r', 'int', 0), 'hidebodyscrollbar' => 'true' === rex_request::get('h', 'string', 'false'), @@ -278,12 +281,9 @@ public function outputJavascript(): never 'cookieSecure' => (bool) $addon->getConfig('cookie_secure', false), 'cookieName' => $addon->getConfig('cookie_name', 'consentmanager'), ]; - echo 'var consent_manager_parameters = ' . json_encode($consent_manager_parameters, JSON_UNESCAPED_SLASHES) . ';' . PHP_EOL . PHP_EOL; + echo 'var consent_manager_parameters = ' . json_encode($consent_manager_parameters, JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT) . ';' . PHP_EOL . PHP_EOL; echo '/* --- Consent-Manager Box Template lang=' . $clang . ' --- */' . PHP_EOL; - echo 'var consent_manager_box_template = \''; - // REXSTAN: meldet «Binary operation "." between array|string and '\';' results in an error.» - // Das ist definitiv falsch und eine Fehlinterpretation wegen obigem «$boxtemplate = str_replace(...» - echo $boxtemplate . '\';' . PHP_EOL . PHP_EOL; + echo 'var consent_manager_box_template = ' . json_encode($boxtemplate, JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT) . ';' . PHP_EOL . PHP_EOL; $lifespan = $addon->getConfig('lifespan', 365); if ('' === $lifespan) { @@ -454,11 +454,6 @@ public static function getJS(): string $boxtemplate = is_string($sprogResult) ? $sprogResult : $boxtemplate; } - // Escape for JavaScript - $boxtemplate = str_replace("'", "\\'", $boxtemplate); - $boxtemplate = str_replace("\r", '', $boxtemplate); - $boxtemplate = str_replace("\n", ' ', $boxtemplate); - $output = ''; // Parameters @@ -477,13 +472,11 @@ public static function getJS(): string 'cookieSecure' => (bool) $addon->getConfig('cookie_secure', false), 'cookieName' => $addon->getConfig('cookie_name', 'consentmanager'), ]; - $output .= 'var consent_manager_parameters = ' . json_encode($consent_manager_parameters, JSON_UNESCAPED_SLASHES) . ';' . PHP_EOL . PHP_EOL; + $output .= 'var consent_manager_parameters = ' . json_encode($consent_manager_parameters, JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT) . ';' . PHP_EOL . PHP_EOL; // Box template $output .= '/* --- Consent-Manager Box Template lang=' . $clang . ' --- */' . PHP_EOL; - $output .= 'var consent_manager_box_template = \''; - // $boxtemplate is guaranteed to be string after above checks - $output .= $boxtemplate . '\';' . PHP_EOL . PHP_EOL; + $output .= 'var consent_manager_box_template = ' . json_encode($boxtemplate, JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT) . ';' . PHP_EOL . PHP_EOL; // Cookie expiration $lifespan = $addon->getConfig('lifespan', 365); diff --git a/package.yml b/package.yml index 5704347b..ed7d8034 100644 --- a/package.yml +++ b/package.yml @@ -1,5 +1,5 @@ package: consent_manager -version: "5.3.2" +version: "5.3.3" author: "Friends Of REDAXO" supportpage: https://redaxo.org/support/community/#slack