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

CVE-2026-103275: Ghost Admin API Information Disclosure

CVE-2026-103275 is an information disclosure flaw in Ghost Admin API that allows staff-level attackers to infer password hashes through filter manipulation. This post explains its impact, affected versions, and mitigation steps.

Published:

CVE-2026-103275 Overview

Ghost versions 5.42.2 through 6.58.0 contain an information disclosure vulnerability in the Admin API bulk post and page edit and delete endpoints. The endpoints accept filters on restricted fields such as authors.password, enabling observable discrepancy attacks [CWE-203]. The flaw stems from an incomplete fix for CVE-2026-70590. Staff-level attackers can infer other staff users' password hashes based on which filters match, then perform offline password-guessing attacks against the recovered hashes.

Critical Impact

Authenticated staff users can extract password hashes of other staff members, including administrators, through boolean inference on filter responses. Successful offline cracking leads to account takeover.

Affected Products

  • Ghost versions 5.42.2 and later
  • Ghost versions prior to 6.58.0
  • Self-hosted Ghost Admin API deployments exposing bulk post and page endpoints

Discovery Timeline

  • 2026-10-01 - CVE-2026-103275 published to the National Vulnerability Database
  • 2026-10-06 - Last updated in NVD database

Technical Details for CVE-2026-103275

Vulnerability Analysis

The Ghost Admin API exposes bulk edit and bulk delete endpoints for posts and pages. These endpoints accept a filter query parameter that is passed to the underlying model layer. The parameter allows filtering on fields that should be restricted, including authors.password.

Because the response reflects whether records matched the supplied filter, an authenticated staff user can submit filters that compare the authors.password column against candidate values character by character. The server's observable response differences disclose whether each comparison succeeded, enabling full hash recovery. This classifies as an observable discrepancy issue [CWE-203].

The original fix for CVE-2026-70590 restricted filterable fields on some endpoints but did not cover the bulk post and page edit and delete handlers. The incomplete coverage left the Admin API inference channel open against staff password hashes.

Root Cause

The bulkEdit and bulkDestroy handlers in ghost/core/core/server/api/endpoints/posts.js and pages.js forwarded frame.options.filter directly into models.Post.findAll without validating that the filter referenced only permitted columns. The permitted-field allowlist from the earlier fix was not applied to these bulk code paths.

Attack Vector

An attacker with staff-level Admin API credentials sends crafted bulk requests. Each request includes a filter expression that tests a byte or substring of another user's authors.password value. The attacker observes which bulk operations affect records, then iteratively narrows the hash value. Recovered bcrypt hashes are then subjected to offline cracking.

javascript
// Patch: ghost/core/core/server/api/endpoints/posts.js and pages.js
// Source: https://github.com/TryGhost/Ghost/commit/5ef16abe85e9b71ac3f1b1e2cbc462802efe3b5b

            method: 'destroy'
        },
        async query(frame) {
-            const postsToDelete = await models.Post.findAll({
-                filter: frame.options.filter,
-                status: 'all',
-                columns: ['status']
-            });
-
-            const allDraft = postsToDelete.length > 0 && postsToDelete.every((post) => {
-                return post.get('status') === 'draft';
-            });
-            if (allDraft) {
+            const result = await postsService.bulkDestroy(frame.options);
+            if (result.allDraft) {
                frame.setHeader('X-Cache-Invalidate', '');
            }

-            return await postsService.bulkDestroy(frame.options);
+            return result;
        }
    },

The patch routes bulk destroy operations through postsService.bulkDestroy, which enforces the field allowlist and no longer passes untrusted filter expressions into direct model queries.

Detection Methods for CVE-2026-103275

Indicators of Compromise

  • Admin API requests to /ghost/api/admin/posts/bulk/ or /ghost/api/admin/pages/bulk/ containing filter expressions that reference authors.password, password, or users.password.
  • Repeated bulk edit or delete requests from the same staff session with incrementally varied filter strings suggesting brute-force inference.
  • High-volume Admin API traffic from a single staff account targeting bulk endpoints without corresponding content changes.

Detection Strategies

  • Parse Admin API access logs for filter= query parameters that include restricted field names such as password, secret, or token.
  • Alert on bulk endpoints invoked with filter strings exceeding a normal complexity threshold or using regex-like comparison operators against user fields.
  • Correlate staff user login events with sustained bulk API query bursts to identify credential-mining behavior.

Monitoring Recommendations

  • Enable verbose Admin API request logging on Ghost deployments and forward logs to a centralized analytics platform.
  • Baseline normal bulk-edit volumes per staff role and alert on deviations exceeding established thresholds.
  • Review staff account activity after upgrading, and rotate any passwords suspected of exposure prior to patching.

How to Mitigate CVE-2026-103275

Immediate Actions Required

  • Upgrade Ghost to version 6.58.0 or later, which enforces an allowlist on filter fields in bulk endpoints.
  • Rotate passwords for all staff users on affected deployments, prioritizing Administrator and Owner roles.
  • Audit Admin API access logs for prior exploitation attempts referencing restricted field names in filters.

Patch Information

The fix is contained in the commit TryGhost/Ghost 5ef16ab and documented in the GitHub Security Advisory GHSA-ghq6-q78f-2cpg. Additional analysis is available in the VulnCheck Advisory on Ghost. The patch moves bulk destroy and edit logic through postsService.bulkDestroy, which validates filter columns against an allowlist.

Workarounds

  • Restrict Admin API network exposure to trusted operator IP ranges using a reverse proxy or firewall rule.
  • Place a web application firewall rule in front of Ghost that blocks requests to /ghost/api/admin/posts/bulk/ and /ghost/api/admin/pages/bulk/ containing the substring password in query parameters.
  • Reduce the number of staff-level accounts and enforce strong, unique passwords with multi-factor authentication to limit abuse potential.
bash
# Example nginx rule to block filter abuse until patching completes
location ~ ^/ghost/api/admin/(posts|pages)/bulk/ {
    if ($args ~* "(password|secret|token)") {
        return 403;
    }
    proxy_pass http://ghost_upstream;
}

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

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.