ghsa-w998-qmw9-mf4m

CVSS 4.8 github
Description

### Summary The 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. ### Details In `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: **File:** `redaxo/src/addons/mediapool/pages/sync.php:119-120` ```php foreach ($diffFiles as $file) { if (is_writable(rex_path::media($file))) { $e = []; $e['label'] = '<label>' . $file . '</label>'; // NO rex_escape! $e['field'] = '<input type="checkbox" name="sync_files[]" value="' . $file . '" />'; // NO rex_escape! $writable[] = $e; } else { $notWritable[] = $file; } } ``` **File:** `redaxo/src/addons/mediapool/pages/sync.php:170` ```php $fragment->setVar('body', '<ul><li>' . implode('</li><li>', $notWritable) . '</li></ul>', false); // $notWritable contains unescaped filenames ``` By 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). ### PoC 1. Place a file named `<img src=x onerror=alert(document.cookie)>.txt` into the REDAXO `/media/` directory (via backup restore or server access) without adding it to the media database. 2. Log in as any backend user with `media[sync]` permission. 3. Navigate to **Mediapool → Sync**. 4. The XSS payload executes immediately, stealing the admin session cookie. ### Impact Stored 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. ### Fix Apply `rex_escape()` to all filename variables before inserting into HTML: ```php $e['label'] = '<label>' . rex_escape($file) . '</label>'; $e['field'] = '<input type="checkbox" name="sync_files[]" value="' . rex_escape($file) . '" />'; // ... $fragment->setVar('body', '<ul><li>' . implode('</li><li>', array_map('rex_escape', $notWritable)) . '</li></ul>', false); ```

Timeline
Published
unknown
Last Modified
unknown
CVSS Details

CVSS details not available.

Affected Products

No product information available.

Weaknesses (CWE)
References
Linked Vulnerabilities

No linked vulnerabilities found.

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "<= 5.21.1"
      },
      "package": {
        "ecosystem": "Packagist",
        "name": "redaxo/source"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "5.21.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-63002"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-79"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-09-23T14:06:04Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "### 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'] = '<label>' . $file . '</label>';          // NO rex_escape!\n        $e['field'] = '<input type=\"checkbox\" name=\"sync_files[]\" value=\"' . $file . '\" />'; // 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->setVar('body', '<ul><li>' . implode('</li><li>', $notWritable) . '</li></ul>', 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 `<img src=x onerror=alert(document.cookie)>.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'] = '<label>' . rex_escape($file) . '</label>';\n$e['field'] = '<input type=\"checkbox\" name=\"sync_files[]\" value=\"' . rex_escape($file) . '\" />';\n// ...\n$fragment->setVar('body', '<ul><li>' . implode('</li><li>', array_map('rex_escape', $notWritable)) . '</li></ul>', false);\n```",
  "id": "GHSA-w998-qmw9-mf4m",
  "modified": "2026-09-23T14:06:04Z",
  "published": "2026-09-23T14:06:04Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/redaxo/core/security/advisories/GHSA-w998-qmw9-mf4m"
    },
    {
      "type": "WEB",
      "url": "https://github.com/redaxo/core/pull/6581"
    },
    {
      "type": "WEB",
      "url": "https://github.com/redaxo/core/commit/2daaa3a30570bc76a82f63fd21fb8c9c2cd5dc7c"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/redaxo/core"
    },
    {
      "type": "WEB",
      "url": "https://github.com/redaxo/core/releases/tag/5.21.2"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "REDAXO: Stored XSS in Mediapool Sync Page via Unescaped Filesystem Filenames"
}
View JSON API Download JSON