Aug 5, 2026·7 min read·2 visits
Ghost CMS versions 6.0.9 through 6.21.0 fail to validate expanded IPv4-mapped IPv6 addresses, enabling remote attackers to bypass SSRF protections and access internal network resources or cloud metadata.
A Server-Side Request Forgery (SSRF) vulnerability exists in the Ghost content management system from version 6.0.9 up to, but not including, 6.21.1. The flaw resides in the 'request-external.js' module, where the IP address validation blocklist fails to account for fully expanded IPv4-mapped IPv6 formats. This allows unauthenticated remote attackers to bypass the private IP filter and initiate unauthorized connections to loopback services, internal subnets, or cloud instance metadata endpoints.
Ghost is an open-source, Node.js-based Content Management System (CMS) utilized extensively for publishing platforms. To support features like oEmbed media previews, external webhooks, and remote asset fetching, the application must initiate outbound HTTP requests. Because these requests are generated server-side, they introduce a significant Server-Side Request Forgery (SSRF) attack surface. To minimize this risk, Ghost implements an IP validation mechanism to block requests targeting local loopback addresses and private networks.
The vulnerability, registered as CVE-2026-53944 and GHSA-wvp2-4qqp-4h3r, resides within this outbound request filtering module. Specifically, the implementation in request-external.js fails to identify and block certain transitional and expanded IPv6 configurations that map to private IPv4 networks. By exploiting this validation gap, an unauthenticated attacker can force the host server to route requests to local and private network segments.
This flaw represents a validation bypass that circumvents the intended security boundary of the application's network sandbox. The vulnerability affects Ghost instances from version 6.0.9 up to, but not including, 6.21.1. In the following sections, we will perform a deep dive into the root cause, exploitation vectors, and the corresponding code patch.
The root cause of CVE-2026-53944 is a parser differential between the application-level validation logic and the system-level address resolution. Ghost uses an internal function named isPrivateIp() within the ghost/core/core/server/lib/request-external.js library to evaluate whether a destination IP address belongs to a prohibited private subnet. The validator processes the address as a string, comparing it against regex patterns representing IPv4 RFC 1918 subnets, link-local addresses, and standard IPv6 local/loopback subnets.
However, IPv6 supports several representation formats, including IPv4-mapped IPv6 addresses. In transitional environments, an IPv4 address can be represented as an IPv6 literal using the ::ffff: prefix. The application's input validation blocklist was designed to handle abbreviated forms of these addresses but failed to account for fully expanded IPv6 representations such as 0:0:0:0:0:ffff:127.0.0.1.
When a user-supplied URL contains an expanded IPv4-mapped IPv6 address, the validator compares the raw, un-normalized string against its blocklist regex patterns. Because the string 0:0:0:0:0:ffff:127.0.0.1 does not match the expected patterns for private IPv4 addresses or standard loopback formats, the validation pass succeeds. Following this verification step, the string is passed to Node.js's underlying network socket layer. The socket layer normalizes the expanded IPv6 address to its standard representation (e.g., ::ffff:127.0.0.1), resolving it directly to the loopback IP 127.0.0.1. Because no secondary validation occurs post-normalization, the outbound request is successfully executed against the local host.
To understand the patch, we must examine how the isPrivateIp function processes the incoming IP address string. In vulnerable versions, the function relies on the ip library and a set of custom regex checks to detect loopback or private ranges. However, it lacks normalization for fully expanded IPv4-mapped IPv6 addresses before performing these checks.
The fix, introduced in commit 9b7f2212970fade08ecbec543b405190471e38d4, inserts defensive logic to process mapped addresses after they have been converted to their normalized IPv6 representation. The normalization phase converts expanded strings like 0:0:0:0:0:ffff:127.0.0.1 to the standard format ::ffff:127.0.0.1.
Here is the vulnerable implementation vs the patched code in ghost/core/core/server/lib/request-external.js:
// Patched logic in ghost/core/core/server/lib/request-external.js
function isPrivateIp(addr) {
// [Existing checks for standard IPv4/IPv6 addresses]
// The patch added the following section:
// Re-check for IPv4-mapped IPv6 after normalization
// Handles expanded forms like 0:0:0:0:0:ffff:127.0.0.1 which normalize to ::ffff:...
const v4DottedNorm = normalized6.match(/^::ffff:(\d[\d.]+)$/i);
if (v4DottedNorm) {
const normV4 = normalizeIPv4(v4DottedNorm[1]);
if (normV4) {
return isPrivateIPv4(normV4);
}
return true;
}
const v4HexNorm = normalized6.match(/^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i);
if (v4HexNorm) {
const hi = parseInt(v4HexNorm[1], 16);
const lo = parseInt(v4HexNorm[2], 16);
const mapped = ((hi >> 8) & 0xff) + '.' + (hi & 0xff) + '.' + ((lo >> 8) & 0xff) + '.' + (lo & 0xff);
return isPrivateIPv4(mapped);
}
return false;
}The patched logic addresses both dotted-decimal and hexadecimal representations of IPv4-mapped IPv6 addresses. If a dotted-decimal pattern matching ^::ffff:(\d[\d.]+)$ is encountered, it extracts the IPv4 substring, normalizes it, and runs it through the private IPv4 range check. For hexadecimal notation (e.g., ::ffff:7f00:1), the patch parses the two 16-bit hex components, extracts the four constituent octets using bitwise right-shift and masking operations, reconstructs the dotted-decimal string, and checks it against isPrivateIPv4(). This ensures that all variants of IPv4-mapped addresses are correctly resolved to their underlying IPv4 representations and validated against the private IP blocklist.
Exploitation of CVE-2026-53944 requires the ability to trigger outbound requests through Ghost features that accept user-provided links. These entry points typically include oEmbed integration cards, remote image uploaders, or administrative webhooks. An unauthenticated or low-privilege user with access to these functions can supply a maliciously crafted URL containing an expanded IPv6 address.
Consider the following Mermaid diagram, which illustrates the exploit sequence and bypass flow:
During the initial validation phase, Ghost's filtering logic evaluates the literal 0:0:0:0:0:ffff:127.0.0.1. Because this string is not recognized as a private IP under the un-patched rules, validation succeeds. The URL is then handed to the Node.js request agent, which resolves it through the OS resolver. The resolver interprets the IPv4-mapped IPv6 structure and routes the outbound socket to the local loopback interface on port 80/443 (or other designated ports).
If the targeted internal endpoint is hosting a management interface, metadata API, or internal system utility, the attacker can extract sensitive information. For instance, in cloud environments such as AWS, Google Cloud, or Microsoft Azure, routing requests to [0:0:0:0:0:ffff:169.254.169.254] allows an attacker to fetch short-lived API tokens and instance configuration details from the Cloud Instance Metadata Service (IMDS).
The direct consequence of this vulnerability is a complete bypass of Ghost's SSRF protection mechanism. Although classified with a CVSS v3.1 base score of 5.8 (Medium) due to standard scoping limits, the practical impact depends heavily on the host environment and co-located services. In a typical containerized or cloud-hosted deployment, an SSRF vulnerability acts as a stepping stone to deeper network penetration.
When hosted on cloud infrastructure, unauthenticated attackers can use this bypass to query the IMDS endpoint at 169.254.169.254. This can lead to the exposure of IAM role credentials, allowing attackers to escalate privileges and access other cloud resources. If the server is co-located with internal microservices, loopback administrative panels, or local database interfaces (e.g., Redis, Memcached, or local databases running on loopback ports), the attacker can execute administrative actions or extract sensitive data.
Furthermore, because the SSRF requests originate from a trusted application server, they bypass firewall rules and network access control lists (ACLs) that would otherwise block external traffic. This makes CVE-2026-53944 a high-priority risk for organizations hosting Ghost instances within private virtual private clouds (VPCs) or sensitive internal corporate networks.
The primary remediation for CVE-2026-53944 is upgrading Ghost to version 6.21.1 or later. The patch corrects the sanitization routine by fully resolving and checking IPv4-mapped IPv6 addresses against private IP blocklists post-normalization. This eliminates the parser differential between the application validation engine and the underlying system network stack.
If an immediate upgrade is not feasible, several defensive workarounds can be deployed at the network and host levels. Organizations should restrict outbound connections from the Ghost application server to private subnets using host-based firewalls (such as iptables or nftables). Specifically, outbound traffic targeting the local loopback address (127.0.0.1), RFC 1918 subnets (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), and link-local addresses (169.254.0.0/16) should be blocked.
To detect potential exploitation attempts, security teams should inspect web server and proxy logs for incoming requests containing bracketed IPv6 literals, particularly those containing the strings :ffff: or consecutive zeros. Security monitoring tools can also be configured with signature-based detection rules to identify outbound connection anomalies from application pools to local administration ports or cloud metadata endpoints.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Ghost TryGhost | >= 6.0.9, < 6.21.1 | 6.21.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-918 (Server-Side Request Forgery) |
| Attack Vector | Network |
| CVSS v3.1 | 5.8 |
| EPSS Score | 0.00197 |
| Impact | Bypass of network sanitization boundary to target local/private endpoints |
| Exploit Status | poc |
| KEV Status | Not Listed |
The web server receives a user-supplied URL/address, validates it insufficiently, and attempts to fetch/connect to that resource, allowing attackers to access internal or localized assets.
A business logic vulnerability in Ghost CMS allows unauthenticated remote users to redeem deactivated or archived promotional subscription offers by programmatically passing old offer identifiers during the checkout session initialization.
Ghost CMS is vulnerable to Server-Side Request Forgery (SSRF) in versions 6.0.9 through 6.21.1. Due to a Time-of-Check to Time-of-Use (TOCTOU) race condition in its outbound fetch validation logic, an attacker can bypass IP blocklists via DNS Rebinding. This allows unauthorized interaction with private networks and local services.
A Server-Side Request Forgery (SSRF) vulnerability exists in the Mobiledoc post-rendering component of Ghost CMS versions 6.19.4 through 6.21.0. This allows authenticated staff users with post creation or editing privileges to force the application server to perform arbitrary outbound HTTP GET requests, targeting internal endpoints, local loopback interfaces, or cloud metadata endpoints.
An authenticated staff-level user can perform a side-channel, boolean-based blind database query attack through the Ghost Admin API to systematically extract the hashed passwords (bcrypt) of other staff users, including administrators, due to insecure filter mapping.
A comprehensive technical analysis of CVE-2026-70591, a Server-Side Request Forgery (SSRF) vulnerability identified in the Ghost Content Management System. The flaw resides in the server-side image fetching mechanism of the ImageSize class, which allows authenticated, staff-level users to force the backend to perform unvalidated HTTP GET requests targeting local or private network services. This report provides an in-depth exploration of the root cause, vulnerable code structures, patch implementations, and mitigation steps.
A path traversal vulnerability (CWE-22) in Ghost CMS versions 1.20.1 through 6.54.0 allows authenticated administrators to escape the backup directory and perform arbitrary file write operations on the hosting system. This vulnerability was resolved in version 6.54.1.