← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
CVE-2026-26980 · CWE-89 · Disclosed 2026-02-20

Ghost is a Node

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
01 · The Real Story

This is a read-only front door that quietly opens the manager’s office

CVE-2026-26980 is an unauthenticated SQL injection in Ghost CMS's Content API. The vulnerable range is Ghost 3.24.0 through 6.19.0, fixed in 6.19.1. The bug sits in slug filter ordering logic: attacker input was interpolated into a raw SQL fragment instead of bound safely, letting a remote attacker pull arbitrary data out of the Ghost database through the public content endpoint.

The vendor's CRITICAL 9.4 call is basically right in the real world. This is not just 'database read' in a vacuum: Ghost stores Admin API keys in that database, and those keys convert a read bug into authenticated site takeover for content, users, themes, and settings. The only meaningful downward pressure is that this is usually app-layer compromise rather than direct host RCE, but active exploitation across 700+ sites erases any temptation to downgrade it.

"Public-facing, no-auth, actively exploited, and it hands attackers site-admin power. Treat this as critical."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Find an internet-facing Ghost site

The attacker identifies a public Ghost deployment exposing the Content API. Because Ghost themes embed the Content API key by design, the endpoint is effectively reachable without secrets, making mass discovery and triage straightforward with normal web scanning.
Conditions required:
  • Ghost is self-hosted and internet reachable
  • Version is between 3.24.0 and 6.19.0
  • Attacker can reach /ghost/api/content/* over HTTP(S)
Where this breaks in practice:
  • Ghost(Pro) was patched immediately, so this mostly hits self-hosted laggards
  • Internal-only Ghost deployments are out of scope
  • Some reverse proxies may rate-limit or geo-block abusive requests
Detection/coverage: ASM and fingerprinting tools can usually identify Ghost, but versioning is often indirect. External scanners may confirm Ghost presence yet still need authenticated host inspection to prove exact version.
STEP 02

Exploit the slug filter SQLi

Using a crafted filter=slug:[...] or related ordering payload, the attacker turns the Content API into a blind SQL oracle. Public tooling and write-ups show practical extraction of database content with simple HTTP GET requests and timing/boolean responses.
Conditions required:
  • Target endpoint accepts attacker-controlled filter/order input
  • No WAF or reverse-proxy rule blocks the known slug:[ pattern
  • Database-backed Ghost instance responds predictably enough for blind extraction
Where this breaks in practice:
  • Blind extraction is slower than a direct dump
  • Aggressive WAF rules and rate limits can break automated exfiltration
  • Timing-based extraction gets noisy behind CDNs or unstable latency
Detection/coverage: Check for repeated requests to /ghost/api/content/ containing slug:[ or slug%3A%5B, plus anomalous response timing. Check Point and SonicWall both published protections/signatures.
STEP 03

Pull Admin API keys from the database

The practical prize is not just posts or users; it is the Ghost Admin API key material stored in the database. Once extracted, the attacker no longer needs the SQLi for persistence and can pivot into normal authenticated admin workflows through the Ghost Admin API.
Conditions required:
  • Successful arbitrary database read
  • Admin API keys present and still valid
  • No key rotation after prior suspected probing
Where this breaks in practice:
  • If operators already rotated keys after patching, post-exploit persistence weakens
  • Some targets may have limited content value even after takeover
Detection/coverage: API and app logs can show unusual admin actions following content API probing. Review Ghost admin activity, staff-user changes, theme changes, and key use after suspicious content API access.
STEP 04

Abuse admin access to poison content

With a valid Admin API key, the attacker can modify posts, inject JavaScript, change themes, or alter site content at scale. The observed real-world campaign used this to plant loaders and fake Cloudflare verification flows, converting trusted sites into malware delivery infrastructure.
Conditions required:
  • Recovered Admin API key works
  • Target still serves modified content to visitors
  • Attacker wants website compromise rather than host-level execution
Where this breaks in practice:
  • Blast radius is mostly the Ghost site and its visitors, not necessarily the underlying server OS
  • Content integrity monitoring or fast editorial review can shorten dwell time
  • Some CDN or CSP configurations may limit downstream script abuse
Detection/coverage: File integrity monitoring will miss many cases because the attacker uses legitimate admin APIs. You need content-diffing, page-body inspection, admin API audit logs, and browser-side CSP/reporting telemetry.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusYes. QiAnXin XLab reported active mass exploitation beginning 2026-05-07, with more than 700 compromised domains later observed.
Known campaignsObserved abuse chained the SQLi into Admin API key theft and then page poisoning / ClickFix delivery on trusted sites, including universities and tech properties.
Proof-of-concept availabilityPublic PoCs exist. SonicWall cites vognik/CVE-2026-26980 and dinosn/ghost-cve-2026-26980 as public exploit / lab repos.
EPSS0.56657 from the user-supplied intel block. That is very high by defender triage standards and lines up with the later exploitation evidence.
KEV statusNot KEV-listed in the CISA catalog reviewed for this assessment, despite public exploitation reporting.
CVSS and interpretationVendor/CNA scored it 9.4 CRITICAL with CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:L. NVD independently assessed a lower 7.5 HIGH vector focused on confidentiality loss, but that underrates the practical impact of stolen Admin API keys.
Affected versionsGhost 3.24.0 through 6.19.0 are affected.
Fixed versionsFixed in Ghost 6.19.1. Ghost's forum says Ghost(Pro) was already patched at release; self-hosters had to update. Official Docker availability was called out separately by the vendor.
Exposure / scaleGhost is broadly internet-facing by design; reporting around this CVE described it as used by 57,000+ websites, and XLab mapped 700+ already-poisoned domains.
Disclosure / creditPublic advisory published in February 2026. Ghost and OSV credit Nicholas Carlini using Claude, Anthropic for responsible disclosure.
04 · The Call

noisgate verdict.

Final Verdict
= UNCHANGED to CRITICAL (9.3/10)

The decisive factor is that this is unauthenticated remote exploitation against a public-facing API, with real campaign evidence showing attackers can convert database reads into valid Ghost admin access. The biggest limiter is that the compromise usually stays at the application/site layer rather than becoming guaranteed server RCE, but that is not enough to pull it below CRITICAL once mass exploitation is on the board.

HIGH Affected-version and patch-range accuracy
HIGH Exploitability assessment for internet-facing self-hosted Ghost
MEDIUM Exact exposure population across enterprise estates

Why this verdict

  • No-auth remote path: the bug is reachable over the public Content API with no login, no prior foothold, and no user interaction.
  • Real-world amplification: XLab and downstream reporting show active exploitation and 700+ poisoned sites, so this is not a theoretical SQLi waiting for a lab PoC.
  • Practical impact exceeds 'read-only': database access yields Ghost Admin API keys, which turns the flaw into authenticated content and site-management takeover.
  • Exposure is broad where it matters: Ghost is a web CMS, so affected instances are commonly internet-facing rather than tucked behind an internal admin plane.
  • Downward pressure exists but is limited: this usually compromises the Ghost application and its visitors, not necessarily the underlying host OS, so I am staying just under the vendor's maximum framing rather than pushing even higher.

Why not higher?

This is not a clean host-level RCE or hypervisor escape. The observed abuse path is app compromise through stolen Ghost admin keys, which is ugly and dangerous but still narrower than guaranteed server takeover across every deployment. Also, Ghost(Pro) was patched immediately, so the exploitable population is disproportionately self-hosted laggards rather than the entire Ghost ecosystem.

Why not lower?

Because the classic downgrade arguments do not hold here. It does not require internal access, credentials, or user interaction, and the exploitation chain has already been industrialized in the wild. A public-facing CMS flaw with live abuse and a direct path to site-admin capability is exactly what a CRITICAL bucket is for.

05 · Compensating Control

What to do — in priority order.

  1. Block the known request pattern at the edge — Deploy a reverse-proxy or WAF rule to block or alert on Content API requests containing slug:[ or slug%3A%5B and related SQLi markers. Because there is active exploitation evidence, do this immediately, within hours rather than waiting for normal change windows.
  2. Rate-limit and monitor the Content API — Apply aggressive rate limits and anomaly detection to /ghost/api/content/* to break blind extraction loops and surface repeated probing. This is a temporary brake, not a fix, and should be in place immediately, within hours for exposed instances.
  3. Rotate Ghost admin-side secrets after patching — Assume exposed sites may have leaked Admin API keys, session secrets, and other database-resident credentials. Rotate them after patching to kill attacker reuse; with active exploitation on record, treat this as immediate post-patch work, within hours for known or suspected exposed sites.
  4. Inspect content and admin activity for silent site poisoning — Review published posts, themes, code injection areas, and Admin API activity for malicious JavaScript or unauthorized content changes. The observed campaign used legitimate app-level admin functionality, so this investigation should begin immediately, within hours on vulnerable internet-facing sites.
  5. Constrain exposure where business permits — If the Content API does not need unrestricted internet access, place it behind allowlists, a CDN rule set, or another access-control layer. That will not cure the vulnerable code, but it reduces reachable population and should be implemented within the CRITICAL remediation cycle, with emergency controls applied first.
What doesn't work
  • Hiding or rotating the Content API key alone does not help; Ghost states it is public by design and not a mitigation.
  • Relying on EDR alone misses the main failure mode because the attacker can stay in normal web/API flows and modify content without dropping host malware.
  • A basic vulnerability scan without version validation is not enough; many tools will fingerprint Ghost but not prove the exact vulnerable release or detect prior key theft.
  • Assuming CDN presence solves it is wrong; the exploit is valid application traffic unless you add targeted rules.
06 · Verification

Crowdsourced verification payload.

Run this on the Ghost host as a user who can read the installation directory; root is not required unless permissions are locked down. Save it as check-ghost-cve-2026-26980.sh, then run bash check-ghost-cve-2026-26980.sh /var/www/ghost or point it directly at your Ghost install root.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check-ghost-cve-2026-26980.sh
# Detects whether a local Ghost installation falls in the vulnerable range for CVE-2026-26980.
# Usage: bash check-ghost-cve-2026-26980.sh /path/to/ghost
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN

set -u

ROOT="${1:-/var/www/ghost}"

CANDIDATES=(
  "$ROOT/current/package.json"
  "$ROOT/current/core/package.json"
  "$ROOT/package.json"
)

PACKAGE_JSON=""
for f in "${CANDIDATES[@]}"; do
  if [ -r "$f" ]; then
    PACKAGE_JSON="$f"
    break
  fi
done

if [ -z "$PACKAGE_JSON" ]; then
  echo "UNKNOWN: could not find readable Ghost package.json under $ROOT"
  exit 2
fi

VERSION=$(sed -n 's/^[[:space:]]*"version"[[:space:]]*:[[:space:]]*"\([^"]\+\)".*/\1/p' "$PACKAGE_JSON" | head -n1)
VERSION="${VERSION#v}"

if [ -z "$VERSION" ]; then
  echo "UNKNOWN: could not parse Ghost version from $PACKAGE_JSON"
  exit 2
fi

version_ge() {
  # returns 0 if $1 >= $2
  [ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -n1)" = "$2" ]
}

version_lt() {
  # returns 0 if $1 < $2
  [ "$1" != "$2" ] && [ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -n1)" = "$1" ]
}

LOWER="3.24.0"
UPPER="6.19.1"

if version_ge "$VERSION" "$LOWER" && version_lt "$VERSION" "$UPPER"; then
  echo "VULNERABLE: Ghost $VERSION detected at $PACKAGE_JSON (affected range: >= $LOWER and < $UPPER)"
  exit 1
fi

if version_ge "$VERSION" "$UPPER" || version_lt "$VERSION" "$LOWER"; then
  echo "PATCHED: Ghost $VERSION detected at $PACKAGE_JSON (not in affected range)"
  exit 0
fi

echo "UNKNOWN: Ghost $VERSION detected, but comparison logic could not classify it"
exit 2
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning, treat every internet-facing self-hosted Ghost instance below 6.19.1 as an emergency. Because there is active exploitation evidence, patch / mitigate immediately, within hours even though the formal noisgate mitigation SLA for CRITICAL is normally <= 3 days; then complete full vendor patching and any required key rotation/integrity review on all affected hosts inside the noisgate remediation SLA of <= 90 days, with the patch itself pulled forward to the front of that window rather than riding the deadline.

Sources

  1. NVD CVE record
  2. Ghost vendor forum advisory
  3. GitHub advisory via OSV mirror
  4. Ghost fix commit
  5. QiAnXin XLab exploitation report
  6. BleepingComputer exploitation coverage
  7. Check Point IPS advisory
  8. CISA KEV catalog
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.