SECURITY ADVISORY / 01

CVE-2026-40789 Exploit & Vulnerability Analysis

Complete CVE-2026-40789 security advisory with proof of concept (PoC), exploit details, and patch analysis.

cve_patchdiff:ameliabooking NVD ↗
Exploit PoC Vulnerability Patch Analysis

The Exploit

Scenario: An unauthenticated attacker makes a single request to the WordPress REST API endpoint that exposes Amelia's settings object.

GET /wp-json/ameliabooking/v1/settings HTTP/1.1
Host: target-site.local
Accept: application/json

Observation: The response body contains an unredacted JSON object holding API keys, OAuth access tokens, and payment gateway credentials in plaintext. The attacker extracts googleAccessToken, outlookAccessToken, gMapApiKey, and payment processor secrets (Stripe, Square, Barion keys) without authentication or privilege check.


What the Patch Did

Before:

'gMapApiKey'                => $this->getSetting('general', 'gMapApiKey'),
'googleAccessToken'         => $this->getSetting('googleCalendar', 'accessToken'),
'outlookAccessToken'        => $this->getSetting('outlookCalendar', 'accessToken'),
'whatsAppPhoneID'           => $this->getSetting('notifications', 'whatsAppPhoneID'),
'whatsAppAccessToken'       => $this->getSetting('notifications', 'whatsAppAccessToken'),
'whatsAppBusinessID'        => $this->getSetting('notifications', 'whatsAppBusinessID'),
'livePOSKey'                => $this->getSetting('payments', 'barion')['livePOSKey'],
'sandboxPOSKey'             => $this->getSetting('payments', 'barion')['sandboxPOSKey'],

After:

'gMapApiKey'                => !empty($this->getSetting('general', 'gMapApiKey')),
'googleAccessToken'         => !empty($this->getSetting('googleCalendar', 'accessToken')),
// 'outlookAccessToken' removed entirely
'whatsAppEnabled'           => Licence\Licence::isFeatureEnabledWithLicense(
    'whatsapp',
    $this->getSetting('featuresIntegrations', 'whatsapp')
) &&
!empty($this->getSetting('notifications', 'whatsAppPhoneID')) &&
!empty($this->getSetting('notifications', 'whatsAppAccessToken')) &&
!empty($this->getSetting('notifications', 'whatsAppBusinessID')),
// Payment keys removed; replaced with feature flag checks

The patch replaced all secret-bearing fields with boolean presence checks using the !empty() operator. Instead of serializing the actual API key or token value, the endpoint now returns only a true/false indicator of whether the credential is configured. Sensitive fields like whatsAppAccessToken, livePOSKey, and sandboxPOSKey were removed from the public response entirely and their presence is inferred indirectly through feature-enabled flags.


Root Cause

CWE-200: Exposure of Sensitive Information to an Unauthorized Actor

The SettingsStorage class's public-facing REST endpoint returns a settings object constructed by calling getSetting() directly on secret keys without filtering. The endpoint does not gate access to the response by user role or nonce; it executes in the REST API's unauthenticated context. An attacker reaches this sink by issuing any GET request to /wp-json/ameliabooking/v1/settings, triggering the settings serialization. The dataflow is: attacker's HTTP GET → WordPress REST router → endpoint handler → getSetting('googleCalendar', 'accessToken') and sibling calls → plaintext token in JSON body → attacker reads response.


Why It Works

The load-bearing line is !empty($this->getSetting(...)). Removing this check would leave the bug entirely exploitable because the sensitive value would be serialized into JSON again. The engineer added the boolean cast to break the semantic link between the configuration truth and its secret representation: the client can now know "yes, Google Calendar is connected" without learning the token itself. The redundant feature-flag checks (Licence::isFeatureEnabledWithLicense()) serve as defence-in-depth, but they do not replace the core control—only the !empty() abstraction prevents token leakage. The removal of fields like outlookAccessToken and payment processor keys is a second layer: fields that carry secrets are stripped from the response schema entirely, so no boolean check can salvage them if the code path reaches serialization.


Hardening Checklist

  • Separate secrets from UI state: Move all API keys, tokens, and credentials into a dedicated, access-controlled storage layer. Query this layer only from internal (non-REST) functions. Public endpoints should reference only feature flags or presence booleans, never the secret values themselves.

  • Apply wp_verify_nonce() and capability checks to all REST endpoints that touch settings. Even endpoints designed for the frontend should include current_user_can('manage_options') or a nonce validation for POST/PUT operations. For GET, consider requiring an authenticated user with read capability at minimum.

  • Use WordPress's Settings API (register_setting() with sanitize_callback and show_in_rest => false) for all secrets. This ensures credentials are never auto-exposed via REST unless explicitly marked and then only after capability checks.

  • Audit all getSetting() call sites in your codebase. For each call that touches a key matching *Token*, *Key*, *Secret*, *Password*, *Credential*, wrap the return value in a check before serialization: !empty($value) or isset($value).

  • Implement response filtering middleware in your REST controller. Before returning a settings object, strip any key whose name hints at sensitivity. Use an allowlist of safe keys rather than a blacklist.


References

  • https://nvd.nist.gov/vuln/detail/CVE-2026-40789

Frequently asked questions about CVE-2026-40789

What is CVE-2026-40789?

CVE-2026-40789 is a security vulnerability. This security advisory provides detailed technical analysis of the vulnerability, exploit methodology, affected versions, and complete remediation guidance.

Is there a PoC (proof of concept) for CVE-2026-40789?

Yes. This writeup includes proof-of-concept details and a technical exploit breakdown for CVE-2026-40789. Review the analysis sections above for the PoC walkthrough and code examples.

How does CVE-2026-40789 get exploited?

The technical analysis section explains the vulnerability mechanics, attack vectors, and exploitation methodology. PatchLeaks publishes this information for defensive and educational purposes.

What products and versions are affected by CVE-2026-40789?

CVE-2026-40789 — check the affected-versions section of this advisory for specific version ranges, vulnerable configurations, and compatibility information.

How do I fix or patch CVE-2026-40789?

The patch analysis section provides guidance on updating to patched versions, applying workarounds, and implementing compensating controls.

What is the CVSS score for CVE-2026-40789?

The severity rating and CVSS scoring for CVE-2026-40789 is documented in the vulnerability details section. Refer to the NVD entry for the current authoritative score.