Incident Alert · Published 2026-05-27
Ghost CMS CVE-2026-26980: 700 Sites Compromised, Two Attack Groups, Here's How to Check Yours
On May 7, threat intelligence researchers at Qianxin's XLab spotted something ugly: Ghost CMS blogs getting their admin API keys stolen and every article quietly poisoned with ClickFix malware loaders. By May 17, the count hit 700+ compromised domains. Harvard's blog was in the list. Oxford's was too. The fix shipped in February. Most people didn't install it. If you run self-hosted Ghost, this is your five-minute check.
What CVE-2026-26980 actually does
Ghost's Content API has a SQL injection flaw that requires no authentication. The main risk is exposure of the Admin API key. That key acts like a bearer token for the admin API, so a stolen key can be used without the normal login flow.
With that key in hand, the attacker calls the Ghost Admin API's PUT /ghost/api/admin/posts/:id/
endpoint in a loop across every article on your site. They inject a tiny JavaScript loader at the
bottom of each post. The loader fetches second-stage code from a cloaking server that fingerprints
visitors, then serves a fake Cloudflare CAPTCHA telling them to paste a command into their Windows
terminal. That command drops a stealer trojan. Your readers become the victims.
The whole process is automated. Scan for Ghost sites, extract key, inject JavaScript, move to next target. Bulk vulnerability scanning into bulk key extraction into bulk injection. No human in the loop.
Affected versions
Ghost 3.24.0 through 6.19.0. Fixed in 6.19.1, released February 19, 2026. If you haven't updated since before that date, you're sitting on the vulnerable version. Ghost Pro (ghost.io managed hosting) auto-updates, so this is a self-hosted problem.
Two attack groups are actively running this campaign. XLab saw sites re-infected by the second group
after the first group's script was cleaned up. Some domains got hit twice in the same day. The first
group's cloaking domain (clo4shara[.]xyz) got blocked by Cloudflare around May 10.
They updated to com-apps[.]cc by May 16 with a new payload that had zero VirusTotal
detections at time of release.
Step 1 - Check your Ghost version
SSH into your server and run:
ghost version Or check via Ghost Admin: Settings - About. If you're below 6.19.1, patch first, then do the rest of this checklist.
ghost update Don't skip the update just because you're about to check for injection. The attacker can re-inject through the same flaw while you're cleaning.
Step 2 - Rotate your Admin API key
Even if you patched, your Admin API key may have been extracted before the patch. Rotate it regardless. Ghost Admin - Settings - Integrations - Custom Integrations - find your integration - Regenerate API key. If you don't have a custom integration listed, check the default Ghost integration.
If you had any third-party tools or scripts using the old key, they'll break. That's fine. Update them with the new key. A broken integration is recoverable. A live attacker with your old key is not.
Step 3 - Scan your articles for injected code
The malicious JavaScript typically appears as a Base64-encoded string inside a
<script> tag appended to the codeinjection_foot field of your
posts. You can check via the Ghost Admin API if you have a content key, or just open each post
in the editor and look at the "Code injection" section in post settings.
For a site with many posts, do this via API instead. With your new Admin API key:
curl -H "Authorization: Ghost YOUR_ADMIN_KEY" \
"https://yourdomain.com/ghost/api/admin/posts/?limit=all&fields=id,title,codeinjection_foot" \
| python3 -m json.tool | grep -A2 "codeinjection_foot"
Any result with "codeinjection_foot": "<script" or a long Base64 string is suspect.
The Kulik Labs cleanup tool on GitHub can also do this for you automatically and clear injections
in bulk after a dry-run review.
Step 4 - Check site-wide code injection
Ghost Admin - Settings - Code injection. Look for anything in the Header or Footer fields that you didn't put there. The post-level injection I described above is per-article, but some attackers also hit the site-wide injection fields. Clear anything unfamiliar.
Step 5 - Review Admin API call logs
XLab recommends keeping 30 days of admin API call history. If you have server access logs, look for
requests to /ghost/api/admin/posts/ with PUT methods from IP addresses you don't
recognize, especially around or before your patch date. That's your incident timeline if you need one.
What you don't need to do
You don't need to wipe Ghost and reinstall unless you find evidence of OS-level compromise (webshells, new cron jobs, unexpected processes). The attack writes into Ghost's database, not onto the filesystem. Patch, rotate keys, clear injected code, and you're clean. If you find OS-level artifacts, that's a different problem and you need a forensics pass before you touch anything.
IoCs to look for
If you're checking logs or inspecting the injected code itself, the known C2 infrastructure from
the two active groups includes clo4shara[.]xyz, com-apps[.]cc, and loader
scripts that use atob() to decode the cloaking server URL. The Base64 string
aHR0cHM6Ly9jbG80c2hhcmEueHl6LzExejc3dTMucGhw decodes to the first-wave cloaking URL.
The new wave uses different encoded strings pointing to com-apps[.]cc. If you see any
atob() calls in your codeinjection fields that you didn't put there, that's the
injection.
XLab's full technical report with payload analysis and malware sample hashes is at blog.xlab.qianxin.com.
If you need help
If you ran the checks above and aren't sure what you're looking at, send the relevant scanner output for a quick exposure review. If the site needs patching, cleanup, or compromise review, use Ping7 CVE repair.
References: CVE-2026-26980 · CVSS 9.4 · Ghost 3.24.0-6.19.0 · Fixed 6.19.1 (2026-02-19) · XLab report (2026-05-21) · BleepingComputer (2026-05-24)