{"id":"CVE-2026-63002","aliases":["EUVD-2026-85331","GHSA-w998-qmw9-mf4m"],"status":"published","title":"REDAXO: Stored XSS in Mediapool Sync Page via Unescaped Filesystem Filenames","description":"REDAXO is a PHP-based content management system. Prior to 5.21.2, redaxo/src/addons/mediapool/pages/sync.php inserts filenames held in $diffFiles from the media filesystem into the Mediapool Sync page without rex_escape(). An attacker who can place an unregistered file with HTML metacharacters in the media directory can execute script in the browser of a backend user with media[sync] permission when that user opens the Sync page, enabling session theft or unauthorized backend actions. This issue is fixed in version 5.21.2.","severity":{"version":"3.1","score":4.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-09","score":0.00197,"percentile":0.0948,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-79"],"published":"2026-09-23T14:05:39Z","modified":"2026-10-28T02:31:02Z","fixes":[{"ecosystem":"Packagist","package":"redaxo/source","fixed_in":["5.21.2"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"Packagist","package":"redaxo/source","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"5.21.1"},{"fixed":"5.21.2"}]}]},{"source":"osv","ecosystem":"Packagist","package":"redaxo/source","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"5.21.2"}]}],"versions":["5.10.0","5.10.0-beta1","5.10.0-beta2","5.10.1","5.11.0","5.11.0-beta1","5.11.1","5.11.2","5.12.0","5.12.0-beta1","5.12.0-beta2","5.12.0-beta3","5.12.1","5.13.0","5.13.0-beta1","5.13.0-beta2","5.13.1","5.13.2","5.13.3","5.14.0","5.14.0-beta1","5.14.0-beta2","5.14.1","5.14.2","5.14.3","5.15.0","5.15.0-beta1","5.15.1","5.16.0","5.16.0-beta1","5.16.1","5.17.0","5.17.1","5.18.0","5.18.1","5.18.2","5.18.3","5.19.0","5.20.0","5.20.1","5.20.2","5.21.0","5.21.0-beta1","5.21.1"]}],"products":[{"vendor":"opnsense","product":"core"},{"vendor":"redaxo","product":"core"},{"vendor":"redaxo","product":"redaxo"}],"references":[{"url":"https://github.com/redaxo/core/security/advisories/GHSA-w998-qmw9-mf4m","tags":["x_refsource_CONFIRM","exploit","Exploit","Vendor Advisory","advisory","web"]},{"url":"https://github.com/redaxo/core/pull/6581","tags":["x_refsource_MISC","Issue Tracking","Patch","fix","web"]},{"url":"https://github.com/redaxo/core/commit/2daaa3a30570bc76a82f63fd21fb8c9c2cd5dc7c","tags":["x_refsource_MISC","Patch","fix","web"]},{"url":"https://github.com/redaxo/core/releases/tag/5.21.2","tags":["x_refsource_MISC","Release Notes","web"]},{"url":"https://github.com/advisories/GHSA-w998-qmw9-mf4m"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/63xxx/CVE-2026-63002.json","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-63002","tags":["advisory"]},{"url":"https://github.com/redaxo/core","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-63002","title":"REDAXO: Stored XSS in Mediapool Sync Page via Unescaped Filesystem Filenames","description":"REDAXO is a PHP-based content management system. Prior to 5.21.2, redaxo/src/addons/mediapool/pages/sync.php inserts filenames held in $diffFiles from the media filesystem into the Mediapool Sync page without rex_escape(). An attacker who can place an unregistered file with HTML metacharacters in the media directory can execute script in the browser of a backend user with media[sync] permission when that user opens the Sync page, enabling session theft or unauthorized backend actions. This issue is fixed in version 5.21.2.","status":"published","published":"2026-09-23T14:05:39.056Z","modified":"2026-09-24T14:26:12.432Z","cvss":[{"version":"3.1","score":4.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N","level":"medium","assessor":"cna"}],"cwes":["CWE-79"],"updated_at":"2026-11-02T14:19:56.284359Z"}],"euvd":[{"id":"EUVD-2026-85331","description":"REDAXO is a PHP-based content management system. Prior to 5.21.2, redaxo/src/addons/mediapool/pages/sync.php inserts filenames held in $diffFiles from the media filesystem into the Mediapool Sync page without rex_escape(). An attacker who can place an unregistered file with HTML metacharacters in the media directory can execute script in the browser of a backend user with media[sync] permission when that user opens the Sync page, enabling session theft or unauthorized backend actions. This issue is fixed in version 5.21.2.","status":"published","published":"2026-09-23T14:05:39Z","modified":"2026-09-24T14:26:12Z","cvss":[{"version":"3.1","score":4.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N","level":"medium"}],"updated_at":"2026-11-02T17:27:57.035497Z"}],"ghsa":[{"id":"GHSA-w998-qmw9-mf4m","title":"REDAXO: Stored XSS in Mediapool Sync Page via Unescaped Filesystem Filenames","description":"### Summary\nThe mediapool sync page (`sync.php`) renders filenames from the `/media` filesystem directory directly into HTML without applying `rex_escape()` (i.e., `htmlspecialchars`). Any file placed in the media directory whose filename contains HTML metacharacters will execute JavaScript in the browser of any backend user who views the sync page.\n\n### Details\nIn `redaxo/src/addons/mediapool/pages/sync.php`, the variable `$diffFiles` is populated from actual filesystem filenames (files in `/media/` not yet registered in the database). These filenames are then rendered without escaping:\n\n**File:** `redaxo/src/addons/mediapool/pages/sync.php:119-120`\n```php\nforeach ($diffFiles as $file) {\n    if (is_writable(rex_path::media($file))) {\n        $e = [];\n        $e['label'] = '\u003clabel\u003e' . $file . '\u003c/label\u003e';          // NO rex_escape!\n        $e['field'] = '\u003cinput type=\"checkbox\" name=\"sync_files[]\" value=\"' . $file . '\" /\u003e'; // NO rex_escape!\n        $writable[] = $e;\n    } else {\n        $notWritable[] = $file;\n    }\n}\n```\n\n**File:** `redaxo/src/addons/mediapool/pages/sync.php:170`\n```php\n$fragment-\u003esetVar('body', '\u003cul\u003e\u003cli\u003e' . implode('\u003c/li\u003e\u003cli\u003e', $notWritable) . '\u003c/li\u003e\u003c/ul\u003e', false);\n// $notWritable contains unescaped filenames\n```\n\nBy contrast, all other filename displays in the codebase use `rex_escape($fname)` (e.g., `media.detail.php:236`, `media.list.php`). The sync page is accessible to any backend user with the `media[sync]` permission (not exclusively admins).\n\n### PoC\n1. Place a file named `\u003cimg src=x onerror=alert(document.cookie)\u003e.txt` into the REDAXO `/media/` directory (via backup restore or server access) without adding it to the media database.\n2. Log in as any backend user with `media[sync]` permission.\n3. Navigate to **Mediapool → Sync**.\n4. The XSS payload executes immediately, stealing the admin session cookie.\n\n### Impact\nStored XSS in the admin panel. An attacker who can place files in the media directory (via admin-level backup restore or server access) can achieve persistent XSS against all users who visit the sync page, including higher-privileged admins. This enables session hijacking, credential theft, and full CMS takeover.\n\n### Fix\nApply `rex_escape()` to all filename variables before inserting into HTML:\n```php\n$e['label'] = '\u003clabel\u003e' . rex_escape($file) . '\u003c/label\u003e';\n$e['field'] = '\u003cinput type=\"checkbox\" name=\"sync_files[]\" value=\"' . rex_escape($file) . '\" /\u003e';\n// ...\n$fragment-\u003esetVar('body', '\u003cul\u003e\u003cli\u003e' . implode('\u003c/li\u003e\u003cli\u003e', array_map('rex_escape', $notWritable)) . '\u003c/li\u003e\u003c/ul\u003e', false);\n```","status":"published","published":"2026-09-23T14:06:04Z","modified":"2026-09-23T14:06:05Z","cvss":[{"version":"3.1","score":4.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N","level":"medium"}],"cwes":["CWE-79"],"updated_at":"2026-11-02T14:41:20.575159Z"}],"nvd":[{"id":"CVE-2026-63002","description":"REDAXO is a PHP-based content management system. Prior to 5.21.2, redaxo/src/addons/mediapool/pages/sync.php inserts filenames held in $diffFiles from the media filesystem into the Mediapool Sync page without rex_escape(). An attacker who can place an unregistered file with HTML metacharacters in the media directory can execute script in the browser of a backend user with media[sync] permission when that user opens the Sync page, enabling session theft or unauthorized backend actions. This issue is fixed in version 5.21.2.","status":"published","published":"2026-09-23T15:17:15.77Z","modified":"2026-10-19T20:36:13.477Z","cvss":[{"version":"3.1","score":4.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N","level":"medium","assessor":"secondary"}],"cwes":["CWE-79"],"updated_at":"2026-11-02T14:12:50.703874Z"}],"osv":[{"id":"CVE-2026-63002","title":"REDAXO: Stored XSS in Mediapool Sync Page via Unescaped Filesystem Filenames","description":"REDAXO is a PHP-based content management system. Prior to 5.21.2, redaxo/src/addons/mediapool/pages/sync.php inserts filenames held in $diffFiles from the media filesystem into the Mediapool Sync page without rex_escape(). An attacker who can place an unregistered file with HTML metacharacters in the media directory can execute script in the browser of a backend user with media[sync] permission when that user opens the Sync page, enabling session theft or unauthorized backend actions. This issue is fixed in version 5.21.2.","status":"published","published":"2026-09-23T14:05:39.056Z","modified":"2026-10-28T02:31:02.244343448Z","cvss":[{"version":"3.1","score":4.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N","level":"medium"}],"cwes":["CWE-79"],"updated_at":"2026-11-02T15:45:13.306117Z"},{"id":"GHSA-w998-qmw9-mf4m","title":"REDAXO: Stored XSS in Mediapool Sync Page via Unescaped Filesystem Filenames","description":"### Summary\nThe mediapool sync page (`sync.php`) renders filenames from the `/media` filesystem directory directly into HTML without applying `rex_escape()` (i.e., `htmlspecialchars`). Any file placed in the media directory whose filename contains HTML metacharacters will execute JavaScript in the browser of any backend user who views the sync page.\n\n### Details\nIn `redaxo/src/addons/mediapool/pages/sync.php`, the variable `$diffFiles` is populated from actual filesystem filenames (files in `/media/` not yet registered in the database). These filenames are then rendered without escaping:\n\n**File:** `redaxo/src/addons/mediapool/pages/sync.php:119-120`\n```php\nforeach ($diffFiles as $file) {\n    if (is_writable(rex_path::media($file))) {\n        $e = [];\n        $e['label'] = '\u003clabel\u003e' . $file . '\u003c/label\u003e';          // NO rex_escape!\n        $e['field'] = '\u003cinput type=\"checkbox\" name=\"sync_files[]\" value=\"' . $file . '\" /\u003e'; // NO rex_escape!\n        $writable[] = $e;\n    } else {\n        $notWritable[] = $file;\n    }\n}\n```\n\n**File:** `redaxo/src/addons/mediapool/pages/sync.php:170`\n```php\n$fragment-\u003esetVar('body', '\u003cul\u003e\u003cli\u003e' . implode('\u003c/li\u003e\u003cli\u003e', $notWritable) . '\u003c/li\u003e\u003c/ul\u003e', false);\n// $notWritable contains unescaped filenames\n```\n\nBy contrast, all other filename displays in the codebase use `rex_escape($fname)` (e.g., `media.detail.php:236`, `media.list.php`). The sync page is accessible to any backend user with the `media[sync]` permission (not exclusively admins).\n\n### PoC\n1. Place a file named `\u003cimg src=x onerror=alert(document.cookie)\u003e.txt` into the REDAXO `/media/` directory (via backup restore or server access) without adding it to the media database.\n2. Log in as any backend user with `media[sync]` permission.\n3. Navigate to **Mediapool → Sync**.\n4. The XSS payload executes immediately, stealing the admin session cookie.\n\n### Impact\nStored XSS in the admin panel. An attacker who can place files in the media directory (via admin-level backup restore or server access) can achieve persistent XSS against all users who visit the sync page, including higher-privileged admins. This enables session hijacking, credential theft, and full CMS takeover.\n\n### Fix\nApply `rex_escape()` to all filename variables before inserting into HTML:\n```php\n$e['label'] = '\u003clabel\u003e' . rex_escape($file) . '\u003c/label\u003e';\n$e['field'] = '\u003cinput type=\"checkbox\" name=\"sync_files[]\" value=\"' . rex_escape($file) . '\" /\u003e';\n// ...\n$fragment-\u003esetVar('body', '\u003cul\u003e\u003cli\u003e' . implode('\u003c/li\u003e\u003cli\u003e', array_map('rex_escape', $notWritable)) . '\u003c/li\u003e\u003c/ul\u003e', false);\n```","status":"published","published":"2026-09-23T14:06:04Z","modified":"2026-09-23T14:15:04.364622513Z","cvss":[{"version":"3.1","score":4.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N","level":"medium"}],"cwes":["CWE-79"],"updated_at":"2026-11-02T15:46:58.401149Z"}]}}
