CVE-2025-48203:
[clickstorm] SEO (cs_seo) TYPO3 extension Cross-site Scripting (XSS) vulnerability
5.1
CVSS ScoreBasic Information
CVE ID
GHSA ID
EPSS Score
-
CWE
Published
5/21/2025
Updated
5/21/2025
KEV Status
No
Technology
PHP
Technical Details
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:L/I:L/A:L/E:F/RL:O/RC:C
Package Name | Ecosystem | Vulnerable Versions | First Patched Version |
---|---|---|---|
clickstorm/cs-seo | composer | >= 9.0.0, < 9.3.0 | 9.3.0 |
clickstorm/cs-seo | composer | >= 8.0.0, < 8.4.0 | 8.4.0 |
clickstorm/cs-seo | composer | >= 7.0.0, < 7.5.0 | 7.5.0 |
clickstorm/cs-seo | composer | >= 6.3.0, < 6.8.0 | 6.8.0 |
Vulnerability Intelligence
Miggo AI
Root Cause Analysis
The vulnerability is a Cross-site Scripting (XSS) issue in the JSON-LD output. I analyzed the provided commit 1cf6c40821102b1f1508fe4e76825569340c8f90
which patches this vulnerability.
- The core of the XSS vulnerability lay in the
Clickstorm\CsSeo\UserFunc\StructuredData::wrapWithLd
function. The original version of this function directly embedded the provided content string into an HTML<script type="application/ld+json">
tag without any escaping. This meant any HTML metacharacters or script tags within the content would be rendered by the browser, causing XSS. The patch fixed this by applyinghtmlspecialchars
to the content. - The
Clickstorm\CsSeo\UserFunc\StructuredData::getJsonLdOfPageOrRecord
function was identified as vulnerable because it fetched JSON-LD data (specifically from$metaData['json_ld']
, which is a likely point for user input) and passed it to thewrapWithLd
function. If this input was malicious,getJsonLdOfPageOrRecord
facilitated the XSS by channeling the tainted data to the vulnerable output function. The patch added JSON decoding and re-encoding as a sanitization step for the data handled by this function before it's passed towrapWithLd
. - The
Clickstorm\CsSeo\Evaluation\TCA\JsonLdEvaluator::evaluateFieldValue
function was involved in validating the JSON-LD data on the backend during save operations. Its original sanitization logic, which only stripped<script>
tags, was insufficient to prevent XSS payloads embedded within the JSON structure itself. This weakness allowed malicious JSON-LD to be stored, which would then be rendered by the vulnerablewrapWithLd
function. The patch improved the validation logic in this function.
All three functions played a role: evaluateFieldValue
in allowing malicious data to be saved, getJsonLdOfPageOrRecord
in processing and passing this data, and wrapWithLd
in unsafely rendering it, which is the direct cause of the XSS.
Vulnerable functions
Clickstorm\CsSeo\UserFunc\StructuredData::wrapWithLd
Classes/UserFunc/StructuredData.php
This function, in its original form, directly concatenated the input `$content` (JSON-LD string) into a `<script>` tag without any HTML escaping. If `$content` contained malicious HTML/JavaScript (e.g., `</script><script>alert(1)</script>`), it would be rendered by the browser, leading to XSS. This is the direct point of injection in the output.
Clickstorm\CsSeo\UserFunc\StructuredData::getJsonLdOfPageOrRecord
Classes/UserFunc/StructuredData.php
This function retrieves JSON-LD data, potentially from user-controlled sources via `$metaData['json_ld']`. In its vulnerable version, it passed this data directly to the `wrapWithLd` function. If the `$metaData['json_ld']` contained malicious script content, this function would facilitate its passage to the vulnerable rendering point in `wrapWithLd`.
Clickstorm\CsSeo\Evaluation\TCA\JsonLdEvaluator::evaluateFieldValue
Classes/Evaluation/TCA/JsonLdEvaluator.php
This function is responsible for server-side validation of the JSON-LD data when a record is saved. The original implementation only attempted to strip `<script>` tags using `preg_replace('#<script(.*?)>|</script>#is', '', $value)`. This sanitization was insufficient as XSS payloads can be embedded within JSON string values without using explicit `<script>` tags (e.g., using event handlers or other contexts within the JSON that could be interpreted as script by the browser when rendered by `wrapWithLd`). This function allowed inadequately sanitized, potentially malicious JSON-LD to be persisted.