CVE-2026-105644 Overview
Ghost, a Node.js content management system, contains a stored cross-site scripting (XSS) vulnerability affecting versions 4.0.0 through 6.66.x. The flaw stems from Ghost storing Scalable Vector Graphics (SVG) files included in content imports without sanitization. An attacker who convinces an Administrator to import a crafted import file can host arbitrary scripts on the site's domain. Those scripts execute in the context of staff users, enabling compromise of admin sessions. The issue is fixed in Ghost version 6.67.0 and tracked under GitHub Security Advisory GHSA-hqq2-xqr2-fmx2.
Critical Impact
Successful exploitation lets an attacker hijack administrator sessions and gain full control over the affected Ghost publication.
Affected Products
- Ghost (Node.js CMS) versions 4.0.0 through 6.66.x
- Self-hosted Ghost installations accepting content imports
- Ghost deployments where Administrators can import files from untrusted sources
Discovery Timeline
- 2026-10-05 - CVE-2026-105644 published to the National Vulnerability Database (NVD)
- 2026-10-06 - NVD record last modified
Technical Details for CVE-2026-105644
Vulnerability Analysis
The vulnerability is a stored cross-site scripting flaw classified under CWE-79. Ghost's content importer accepted SVG files on the basis of file extension alone and persisted them to storage without inspecting or sanitizing their contents. SVG is an XML format that supports inline <script> elements and event handler attributes. Because the resulting files are served from the Ghost site's own origin, any JavaScript inside them runs with full access to that origin, including session cookies belonging to signed-in staff users. The Ghost Administrator role is required to perform the import, so exploitation depends on social engineering. Once the file is hosted, however, every staff user who loads the SVG URL in the admin interface is at risk of session hijacking.
Root Cause
The import handler at ghost/core/core/server/data/importer/handlers/image.js identified images by extension and bypassed the sanitization applied to direct SVG uploads. There was no content-type validation and no call to an SVG sanitizer before files were written to the configured storage adapter.
Attack Vector
An attacker crafts a malicious Ghost import archive containing an SVG with embedded JavaScript. The attacker then convinces an Administrator to import the archive through the admin UI. After import, the SVG is served from the Ghost domain. Any staff user who views the file executes the attacker's script, exposing admin session tokens and enabling account takeover.
// Patch excerpt: ghost/core/core/server/data/importer/handlers/image.js
const _ = require('lodash');
const path = require('path');
const logging = require('@tryghost/logging');
const config = require('../../../../shared/config');
const urlUtils = require('../../../../shared/url-utils').default;
const adapterManager = require('../../../services/adapter-manager').default;
const { isAllowedImageContent, isSvgExtension } = require('../../../lib/image/image-content');
const { sanitizeSvgFile } = require('../../../lib/image/svg-sanitizer');
const { promisePool } = require('../../../lib/promise-pool');
// Imports can hold thousands of images, so bound the number of open files
const VALIDATION_CONCURRENCY = 10;
/**
* Files are picked out of the import by extension alone, so check the
* contents match before they are stored as images. SVGs are sanitized in
* place, the same as SVG uploads.
*/
const isValidImage = async (file, extensions) => {
const ext = path.extname(file.name).toLowerCase();
if (isSvgExtension(ext)) {
return sanitizeSvgFile(file.path, ext === '.svgz');
}
return isAllowedImageContent(file.path, extensions);
};
Source: GitHub Commit 1be06f4
Detection Methods for CVE-2026-105644
Indicators of Compromise
- SVG or SVGZ files in Ghost content storage containing <script> tags, on* event handlers, or javascript: URIs.
- Recent content import jobs executed by Administrator accounts from unverified sources.
- Unexpected staff user logins, API token creations, or role changes following an import.
Detection Strategies
- Scan the Ghost content/images directory for SVG files containing executable XML elements such as <script>, <foreignObject>, or event attributes like onload and onclick.
- Review Ghost admin audit logs for importer activity that preceded any suspicious administrative changes.
- Monitor web server access logs for direct requests to SVG assets originating from authenticated admin sessions.
Monitoring Recommendations
- Alert on new admin or staff account creation and on password or two-factor authentication changes immediately following an import event.
- Track outbound HTTP requests from browsers viewing admin pages to detect script-driven data exfiltration.
- Instrument the Ghost admin domain with Content Security Policy violation reporting to surface unexpected inline script execution.
How to Mitigate CVE-2026-105644
Immediate Actions Required
- Upgrade Ghost to version 6.67.0 or later, which sanitizes SVG files during import.
- Audit all SVG assets uploaded or imported since the deployment first reached version 4.0.0 and remove any file containing executable content.
- Rotate Ghost staff user sessions, API keys, and integration tokens if a suspicious import occurred.
Patch Information
The fix landed in Ghost pull request #31060 and is included in the Ghost v6.66.0 release line with full remediation in 6.67.0. The patch adds sanitizeSvgFile to the import pipeline and enforces content-type validation through isAllowedImageContent. See GitHub Security Advisory GHSA-hqq2-xqr2-fmx2 for the complete advisory.
Workarounds
- Restrict the Administrator role to a minimal, trusted set of users until the upgrade is applied.
- Reject import archives from any source that has not been independently verified.
- Serve user-uploaded content from a separate origin to isolate stored scripts from the admin session cookie scope.
# Verify installed Ghost version and upgrade
ghost version
ghost update 6.67.0
# Search existing content storage for SVG files with embedded scripts
grep -ril -E '<script|on[a-z]+=|javascript:' /var/lib/ghost/content/images --include='*.svg*'
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.