Listen to this Post
The vulnerability arises from improper cache isolation in Ghost’s frontend when deployed behind a shared caching layer (e.g., Fastly, Cloudflare, nginx proxy_cache). Ghost uses the `x-ghost-preview` HTTP header to enable preview functionality for unauthenticated users – this header allows a request to render draft content that is not yet published. In versions prior to 6.37.0, the caching middleware did not set a `no-cache` policy on responses that were generated using this header. Consequently, when an unauthenticated attacker sends a request with a crafted `x-ghost-preview` header, the resulting preview response – which may contain attacker-controlled content or sensitive user-specific data – is stored in the shared cache. Subsequent visitors requesting the same URL receive this poisoned cached response instead of the genuine page.
The attack chain is straightforward: the attacker identifies a publicly accessible page that is cached (e.g., a blog post or homepage). They then issue a GET request to that page while including the `x-ghost-preview` header with a value that triggers a preview state (e.g., a draft post ID or a preview secret). Because the cache layer does not differentiate preview requests from normal ones, the cache key does not include the `x-ghost-preview` header, so the poisoned response is stored under the same cache key as the public page. When a legitimate visitor later requests the same page, they receive the cached preview output, which may include arbitrary HTML/JavaScript injected by the attacker (stored XSS) or expose draft content intended only for the author.
If Ghost’s frontend and admin panel are hosted on the same domain, this stored XSS can be escalated to session hijacking: the attacker’s injected script can read cookies, make authenticated API requests, and ultimately take over staff user accounts. Even without XSS, the cache poisoning can deface the site or leak unpublished content. The vulnerability is present from Ghost v4.0 up to v6.36.0 and is fixed in v6.37.0. A workaround exists by configuring the caching layer to bypass cache for any request containing the `x-ghost-preview` header.
DailyCVE Form:
Platform: ……. Ghost CMS
Version: …….. v4.0 – v6.36.0
Vulnerability :…… Cache-Poisoning XSS
Severity: ……. Critical (CVSS 9.6)
date: ………. 2026-06-24
Prediction: …… Already patched v6.37.0
What Undercode Say:
Check current Ghost version (CLI install) ghost version Check current Ghost version (Docker) docker exec <container_name> ghost --version Verify if cache headers are missing (example with curl) curl -I https://example.com/ | grep -i cache-control Test for vulnerability – send x-ghost-preview header curl -H "x-ghost-preview: draft-secret-123" https://example.com/hello-world/ Check response for cache poisoning (look for preview content in cached response) curl -I -H "x-ghost-preview: draft-secret-123" https://example.com/hello-world/
Exploit:
Step 1 – Attacker sends request with x-ghost-preview header to poison cache
curl -H "x-ghost-preview: 12345" "https://target.com/popular-post" -o poisoned.html
Step 2 – Inject XSS payload via preview parameter (if preview input is reflected)
curl -H "x-ghost-preview: <script>alert('XSS')</script>" "https://target.com/popular-post"
Step 3 – Legitimate visitor accesses the same URL and receives poisoned cached response
(No special headers needed – cache serves the stored preview output)
Step 4 – If admin panel is on same domain, stolen cookies can be used to takeover account
Attacker's script can exfiltrate session cookies to attacker-controlled server
Protection:
- Upgrade to Ghost v6.37.0 or later – this is the definitive fix.
- If unable to upgrade immediately, configure your caching layer (Cloudflare, Fastly, nginx) to bypass cache for all requests containing the `x-ghost-preview` header.
– nginx example:
if ($http_x_ghost_preview) {
proxy_cache_bypass 1;
proxy_no_cache 1;
}
– Cloudflare Workers / Page Rules: Create a rule to disable cache when `x-ghost-preview` header is present.
3. If you suspect a compromise, use the “Reset all authentication” option under Settings → Danger Zone (available since Ghost v6.41.0) to invalidate all active sessions.
Impact:
- Cache Poisoning: Attackers can inject malicious or unintended content into the shared cache, affecting all visitors of a poisoned page.
- Stored XSS: If the preview functionality reflects user-controlled input, the poisoned cache can deliver persistent JavaScript payloads to every visitor.
- Account Takeover: When the frontend and admin panel share the same domain, the injected script can steal session cookies and perform authenticated actions, leading to full compromise of staff accounts.
- Data Leakage: Unpublished draft content can be exposed to unauthorized users through the cached preview responses.
- Reputation Damage: Defacement or misinformation served from a trusted domain can erode user trust and damage the site’s credibility.
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

