Skip to content
Noroxi
Research7 min read

Essential Blocks: Contributor Reads the Admin's Google Maps API Key

A missing capability check in Essential Blocks for Gutenberg lets any Contributor read the admin's Google Maps API key. Root cause, fix and detection.

Noroxi TeamPenetration testing and security consulting

Abstract. A read-only AJAX handler in Essential Blocks for Gutenberg hands the administrator's Google Maps API key to any Contributor. The endpoint checks a nonce and the edit_posts capability, but neither gate establishes that the caller is allowed to read an administrator secret — a textbook Missing Authorization flaw (CWE-862). This write-up covers the root cause, why a low-privilege account reaches the sink, and the prevention and detection steps that follow from it. The plugin is unpatched as of writing, so the operational proof of concept stays withheld under coordinated disclosure until a fix ships.

Keywords: WordPress security, Missing Authorization, CWE-862, broken access control, capability checks, API key disclosure, secure coding.

1. Introduction

Essential Blocks for Gutenberg ships its block library to more than 200,000 sites. At that scale a single forgotten check stops being a local bug: one missing line can expose the same credential across hundreds of thousands of installations at once.

The defect is missing authorization, one of the most common classes in the WordPress ecosystem. An administrator's Google Maps API key is served by an endpoint that confirms a request is legitimate but never asks whether the caller is entitled to read it. That same shape — right request, wrong reader — turns up across plugins and slips past review easily, which is what makes it worth taking apart.

2. Affected component

PluginEssential Blocks for Gutenberg — slug essential-blocks
Tested version6.4.6 (current at time of testing)
Active installations200,000+
Vulnerability typeMissing Authorization / Sensitive Information (API key) Disclosure
CWECWE-862 Missing Authorization / CWE-200
Required privilegeContributor (any user with edit_posts; lacks manage_options)
CVSS 3.1~5.4 (Medium) AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
StatusFresh, confirmed in code and reproduced on a localhost lab

3. Root cause in the code

The AJAX action google_map_api_key reads the site-wide, admin-configured Google Maps API key out of the eb_settings option and returns it. Two things stand between a request and that secret: a nonce, and the edit_posts capability. Not manage_options.

php
// Blocks/GoogleMap.phppublic function google_map_api_key_callback(){    if ( ! wp_verify_nonce( sanitize_key( $_POST['admin_nonce'] ), 'admin-nonce' ) ) {        wp_send_json_error( __( 'Nonce verification failed!', 'essential-blocks' ) );    }    if ( ! current_user_can( 'edit_posts' ) ) {               // <-- WRONG CHECK: low cap; should be manage_options        wp_send_json_error( __( 'You are not authorized!', 'essential-blocks' ) );    }    $settings = get_option( 'eb_settings' );    if ( is_array( $settings ) && isset( $settings['googleMapApi'] ) ) {        wp_send_json_success( $settings['googleMapApi'] );     // <-- returns the admin's API key    }    ...}

Both guards are the wrong kind of guard for what the handler returns.

wp_verify_nonce() is not an authorization check. It confirms that a request came from a genuine logged-in session and was not forged by a third party — CSRF protection, nothing more. A nonce is bound to the user, never to a capability, so it says nothing about what that user is allowed to do.

The edit_posts check is the second mistake. The value on the wire is an administrator setting, and the capability that governs who reads or changes site-wide integration settings is manage_options. Put an admin secret behind edit_posts — a capability every Contributor and Author already holds — and the "authorization" gate waves through precisely the people it should be turning away.

The plugin's sibling save handler for the same setting is gated correctly, which makes this a classic asymmetry: the write path is protected and the read path is not.

4. How the flaw is reached (conceptual)

A Contributor is a low-trust role. They can draft posts, but they cannot publish, install plugins, or view site settings. Reaching this handler takes two things, and WordPress hands a Contributor both as a matter of course:

  1. A valid nonce for the action. The plugin localizes admin-nonce into a JavaScript object on the block-editor screen for every user who can open it. Nonces are issued per user and carry no capability scope, so a Contributor who opens the ordinary "new post" editor is served a working nonce for this action as a normal part of the page. Obtaining it takes no trick.
  2. A way to call the endpoint. admin-ajax.php answers any authenticated user. Once the handler runs with that nonce, the only gate left is the edit_posts check — and the Contributor clears it.

So the "authorization" this endpoint performs is already satisfied by the attacker's ordinary privileges. The nonce proves the request is real; the capability check proves the caller can edit posts. Neither one proves the thing that matters, that the caller may read an administrator secret. The admin-only Google Maps API key ends up disclosed to a role that should never see it.

The literal request sequence, parameter values, and any runnable commands are deliberately left out while the plugin is unpatched.

5. Impact assessment

A Contributor who has no business touching site-wide integration secrets can read the administrator-configured Google Maps API key. The fallout lands on the site owner's Google account:

  • Quota and billing abuse. A leaked Maps key can be driven hard to burn through the owner's quota and, past that, their billing allowance.
  • Use on unauthorized domains. Weak or absent HTTP-referrer and application restrictions let the key work from attacker-controlled sites.

The vector AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N captures this shape: reachable over the network, low complexity, low privilege, no user interaction, high confidentiality impact as the secret is fully disclosed, and no direct hit to integrity or availability. That lands at an honest Medium (~5.4).

6. Remediation

Authorize on the capability that actually governs the setting. Swap the check in google_map_api_key_callback() from edit_posts to manage_options, so the read path matches the save path:

php
if ( ! current_user_can( 'manage_options' ) ) {    wp_send_json_error( __( 'You are not authorized!', 'essential-blocks' ) );}

Until an official fixed release ships, site owners can cut their exposure:

  • Audit Contributor and Author accounts and drop any that are untrusted or dormant.
  • Restrict the Google Maps API key in the Google Cloud console. Set HTTP-referrer restrictions to your own domains and scope the key to only the APIs it actually calls, so a leaked key is far less useful elsewhere.
  • Rotate the key if untrusted users have held editor access, and watch Google Cloud usage for anomalies.

7. Detection and hardening for site owners

Drawn straight from how the flaw works:

  • Flag unexpected calls to the admin-ajax.php action google_map_api_key coming from Contributor or Author sessions. Legitimately, only an administrator configuring the setting triggers that read.
  • Watch the Maps key in Google Cloud. Sudden usage spikes, requests from unfamiliar referrers or regions, and billing alerts are the signals that the key has leaked.
  • Apply least privilege. Hand out Contributor and Author roles only where they are needed; with no low-privilege accounts, the flaw has nothing to act on.
  • Consider a virtual patch. A WAF rule that blocks or challenges this specific AJAX action for non-administrator sessions is a reasonable stopgap — not a replacement for upgrading once a fixed version lands.
  • Keep plugins current and apply the vendor's fixed release as soon as it is out.

8. The broader lesson

The principle is simple and broken constantly: authentication and CSRF protection are not authorization. A nonce tells you a request is genuine; it tells you nothing about whether the requester is entitled to the data. Any endpoint that returns or changes privileged data owes it an explicit capability check matched to how sensitive that data is — not to whichever broad capability happens to be in reach.

The second lesson is symmetry. When a setting has a read path and a write path, both deserve the same guard, because an attacker will always probe the one that was forgotten. Reviewers and automated checks should flag any handler that returns an administrative option value behind anything weaker than the capability that governs that option.

9. Responsible disclosure

The issue was reported to the plugin vendor privately and in good faith under a coordinated-disclosure process. Full proof-of-concept detail — the exact request sequence and parameter values — is withheld from this public article until a fixed version is available, or until the agreed disclosure deadline, whichever comes first. Nothing that would enable live exploitation has been published.

All testing ran in an authorized, isolated localhost lab on infrastructure the researcher controls, using the publicly available GPL plugin. No third-party or production systems were touched. The test environment and accounts were removed once the issue was reproduced.

References

Published for defensive and educational purposes. Noroxi LLC conducts authorized security research only; operational exploit detail is withheld until a fix is available.

Exploited this week · every Monday

New KEV entries, fresh PoCs, WordPress triage and what to do this week. No account needed.

Your address is used only for this email and never shared.

Up next

GiveWP 4.18.0: Unauthenticated Donor-Data Disclosure (CWE-862)