Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-70589

CVE-2026-70589: Ghost CMS Auth Bypass Vulnerability

CVE-2026-70589 is an authentication bypass flaw in Ghost CMS that allows users to redeem inactive subscription offers due to missing validation. This article covers technical details, affected versions, and mitigations.

Updated:

CVE-2026-70589 Overview

CVE-2026-70589 is an input validation vulnerability in Ghost, a Node.js content management system used to publish and monetize digital content. The flaw affects Ghost versions 4.22.0 through 6.54.0. A missing validation check in the members API router controller allowed users to redeem subscription offers that were no longer active. The issue is fixed in Ghost 6.54.1. The vulnerability is tracked under CWE-20: Improper Input Validation.

Critical Impact

Attackers can redeem archived or expired subscription offers, obtaining discounted or promotional pricing that publishers had already withdrawn from circulation.

Affected Products

  • Ghost (Node.js CMS) versions 4.22.0 through 6.54.0
  • Ghost self-hosted deployments running affected versions
  • Ghost(Pro) instances pending upstream update to 6.54.1

Discovery Timeline

  • 2026-08-04 - CVE-2026-70589 published to NVD
  • 2026-08-05 - Last updated in NVD database

Technical Details for CVE-2026-70589

Vulnerability Analysis

Ghost exposes a members API that lets visitors redeem promotional offers tied to subscription tiers. The offer redemption endpoint in ghost/core/core/server/services/members/members-api/controllers/router-controller.js looked up an offer by identifier and forwarded it to the checkout logic. The controller did not verify the offer's status field before proceeding. As a result, offers marked as archived or otherwise inactive by the publisher remained functionally redeemable if the offer ID was still known or guessable.

An attacker who retained a previously shared offer URL, or who obtained the offer identifier through browser history, referral links, or leaked marketing material, could complete a checkout at the archived promotional price. Publishers lost the ability to reliably retire pricing promotions, undermining subscription revenue controls.

Root Cause

The root cause is a missing state check between offer retrieval and offer application. The controller trusted that any offer record returned from the data layer was eligible for redemption. Lifecycle state, expressed through the offer.status property, was not evaluated against the required active value.

Attack Vector

Exploitation occurs over the network against the public members API. No authentication is required, but the attacker must know a valid offer identifier for an archived offer, which raises attack complexity. Successful redemption produces limited confidentiality and integrity impact by granting unauthorized access to retired pricing tiers.

javascript
// Patch from ghost/core/core/server/services/members/members-api/controllers/router-controller.js
// Source: https://github.com/TryGhost/Ghost/commit/d91c0fc52dfc987d71a9803dbcbe6447d21b92fb
                });
            }

+            if (offer.status && offer.status !== 'active') {
+                throw new BadRequestError({
+                    message: tpl(messages.offerArchived),
+                    context: 'Offer with id "' + offerId + '" is no longer active'
+                });
+            }
+
            if (!offer.tier) {
                throw new BadRequestError({
                    message: 'Offer does not have a tier'

The patch inserts an explicit status check. Any offer whose status is set and not equal to active now raises a BadRequestError with the offerArchived message before reaching tier resolution.

Detection Methods for CVE-2026-70589

Indicators of Compromise

  • Successful checkout events on the members API referencing offer identifiers that the publisher previously archived in the Ghost admin panel.
  • New subscriber records created against pricing tiers that no longer have an active promotional offer attached.
  • Spikes in redemptions for a single offer ID after that offer's advertised campaign window closed.

Detection Strategies

  • Review Ghost application logs for POST requests to the members create-checkout-session endpoint that include offerId query parameters mapped to archived offers.
  • Correlate Stripe or payment processor discount usage against the offer status timeline exported from Ghost.
  • Compare the running Ghost version reported by /ghost/api/admin/site/ against the fixed release 6.54.1.

Monitoring Recommendations

  • Enable structured request logging on the Ghost members API and forward events to a centralized log platform for retention and search.
  • Alert on any redemption of an offer whose lifecycle state transitioned away from active prior to the checkout timestamp.
  • Audit new member sign-ups on a scheduled cadence, cross-referencing applied offers with the current offer catalog.

How to Mitigate CVE-2026-70589

Immediate Actions Required

  • Upgrade Ghost to version 6.54.1 or later on all self-hosted and managed deployments.
  • Rotate or delete offer identifiers for promotions that must not be redeemable, since URL knowledge alone previously enabled abuse.
  • Reconcile recent subscriber records against the archived offer list and revoke or adjust subscriptions that used ineligible offers.

Patch Information

Ghost 6.54.1 introduces the missing offer.status !== 'active' check in the members API router controller. See the GitHub Security Advisory GHSA-4wx2-7gvj-qfq3 and the upstream commit d91c0fc for the authoritative fix.

Workarounds

  • Delete archived offers instead of leaving them in an inactive state until the upgrade is applied.
  • Place a reverse proxy rule in front of Ghost that blocks requests to the members create-checkout-session route when the offerId matches a known archived identifier.
  • Restrict access to offer URLs by regenerating offer codes for any campaigns whose links have been distributed publicly.
bash
# Verify the running Ghost version and upgrade to the patched release
ghost version
ghost update 6.54.1

# Confirm the fix is present in the deployed source tree
grep -n "Offer with id" \
  current/core/server/services/members/members-api/controllers/router-controller.js

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.