CVE-2026-54197

GetGenie – AI Content Writer with Keyword Research & SEO Tracking <= 4.4.1 - Unauthenticated Information Exposure

mediumExposure of Sensitive Information to an Unauthorized Actor
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
4.4.2
Patched in
11d
Time to patch

Description

The GetGenie – AI Content Writer with Keyword Research & SEO Tracking plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 4.4.1. This makes it possible for unauthenticated attackers to extract sensitive user or configuration data.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Low
Confidentiality
None
Integrity
None
Availability

Technical Details

Affected versions<=4.4.1
PublishedJune 15, 2026
Last updatedJune 25, 2026
Affected plugingetgenie

What Changed in the Fix

Changes introduced in v4.4.2

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-54197 ## 1. Vulnerability Summary The **GetGenie AI** plugin (up to version 4.4.1) contains an information exposure vulnerability in its initialization logic. The function `genie_header_script_data()` is designed to prepare configuration data and SEO-related …

Show full research plan

Exploitation Research Plan - CVE-2026-54197

1. Vulnerability Summary

The GetGenie AI plugin (up to version 4.4.1) contains an information exposure vulnerability in its initialization logic. The function genie_header_script_data() is designed to prepare configuration data and SEO-related post meta for the plugin's editors (Elementor, Bricks, Oxygen, and Gutenberg).

However, the plugin incorrectly allows unauthenticated users to trigger this function on the frontend by providing specific query parameters (bricks or ct_builder). When triggered, the function retrieves sensitive data, including a wp_rest nonce and internal SEO metadata for the current post, and exposes it in the page source (typically via wp_localize_script or a script block).

2. Attack Vector Analysis

  • Endpoint: Any public post or page on the WordPress site.
  • Trigger Parameter: bricks=1 or ct_builder=1 in the GET request.
  • Authentication: None (Unauthenticated).
  • Vulnerable Component: getgenie.php, specifically the genie_header_script_data() function and its conditional hook registration.
  • Impact: Exposure of a valid wp_rest nonce (which can be used for unauthorized REST API interactions) and proprietary SEO keyword/content metadata.

3. Code Flow

  1. Entry Point: In getgenie.php, the plugin checks for builder-specific query strings:
    if (isset($_GET['bricks'])) {
        add_action('wp_enqueue_scripts', 'genie_header_script_data');
    }
    if (isset($_GET['ct_builder'])) {
        add_action('wp_enqueue_scripts', 'genie_header_script_data');
    }
    
  2. Execution: When a user visits a URL like http://victim.com/?bricks=1, the wp_enqueue_scripts hook triggers genie_header_script_data().
  3. Data Collection:
    • The function calls get_the_ID() to identify the current post.
    • It iterates through keys defined in getgenie_blogwizard_store_objects() (e.g., keyword, serpData, keywordData).
    • It retrieves this data from post meta using the prefix getgenie_blogwizard_.
  4. Exposure: The function generates a wp_rest nonce using wp_create_nonce('wp_rest') and bundles it into a $config array. Although the provided snippet is truncated, the function's purpose (indicated by its name and context) is to output this data to the header/script localized data, making it visible in the HTML.

4. Nonce Acquisition Strategy

This vulnerability is itself a nonce leak. No nonce is required to trigger the exploit. The objective of the exploit is to obtain the wp_rest nonce.

  • Trigger: Visit a page with ?bricks=1.
  • Extraction:
    1. The configuration is likely localized under a specific JavaScript object name. Based on standard GetGenie naming conventions, we look for a script block containing genie_config or similar.
    2. Using browser_eval, we can check for: window.getgenie_config or scan the HTML source for the string "restNonce".

5. Exploitation Strategy

Step 1: Identify a Target Post

Locate any published post ID on the target site (e.g., Post ID 1).

Step 2: Trigger Information Exposure

Request the post with the trigger parameter.

  • Method: GET
  • URL: http://<target-ip>/?p=1&bricks=1
  • Headers: Standard browser headers.

Step 3: Extract Sensitive Data

Parse the HTML response for the configuration object.

  • Payload Location: Search for <script> tags containing JSON data.
  • Expected Fields:
    • restNonce: A 10-character alphanumeric WordPress nonce.
    • keyword: SEO keyword data for the post.
    • serpData: Competitive analysis data.

6. Test Data Setup

To verify the exposure of "Sensitive Information" (specifically post meta):

  1. Create a post using WP-CLI:
    wp post create --post_status=publish --post_title="SEO Target" --post_content="Content" (Assume ID is 123).
  2. Add GetGenie-specific meta to that post:
    wp post meta add 123 getgenie_blogwizard_keyword '"secret-proprietary-keyword"'
    wp post meta add 123 getgenie_blogwizard_seoCountry '"US"'

7. Expected Results

The response body should contain the following JSON structure (likely inside a <script> tag):

{
    "post_id": 123,
    "keyword": "secret-proprietary-keyword",
    "seoCountry": "US",
    "restNonce": "[a-z0-9]{10}",
    "baseApi": ".../wp-json/getgenie/v1/"
}

8. Verification Steps

  1. Check Meta Exposure: Confirm the string "secret-proprietary-keyword" appears in the HTML source when ?bricks=1 is used, and is absent when it is not.
  2. Verify Nonce Validity:
    Use the extracted restNonce to perform a REST API request that requires authentication (e.g., listing users or plugin settings) to see if it accepts the nonce.
    http_request(POST, "/wp-json/wp/v2/posts/123", headers={"X-WP-Nonce": "EXTRACTED_NONCE"}). If it returns a 403 permission error rather than a 403 invalid nonce error, the nonce is valid.

9. Alternative Approaches

  • Oxygen Builder Trigger: If bricks is disabled or blocked, try ?ct_builder=1.
  • Admin Head Exposure: If the frontend trigger fails, check if the data is exposed on the login page or other public-facing admin-ajax endpoints if the plugin incorrectly initializes admin_head hooks globally.
  • Elementor Editor: If the site uses Elementor, the elementor/editor/after_enqueue_scripts hook might expose this data on the Elementor editor load screen, which might have different access control checks.
Research Findings
Static analysis — not yet PoC-verified

Summary

The GetGenie AI plugin for WordPress allows unauthenticated attackers to expose sensitive configuration data and SEO metadata by providing specific query parameters like 'bricks' or 'ct_builder'. This occurs because the plugin incorrectly hooks a data-exposure function to the frontend without verifying user permissions, leaking a valid 'wp_rest' nonce and internal keyword data.

Vulnerable Code

// getgenie.php lines 145-151
if (isset($_GET['bricks'])) {
    add_action('wp_enqueue_scripts', 'genie_header_script_data');
}

if (isset($_GET['ct_builder'])) {
    add_action('wp_enqueue_scripts', 'genie_header_script_data');
}

---

// getgenie.php lines 218-233
$blog_wizard_data = [
    'post_id' => get_the_ID(),
];

$blogwizard_objects = getgenie_blogwizard_store_objects();
foreach ($blogwizard_objects as $object) {
    $blog_wizard_data[$object] = json_decode(
        get_post_meta(
            get_the_ID(),
            GETGENIE_BLOGWIZARD_PREFIX . $object,
            true
        )
    );
}

$token = new \GenieAi\App\Auth\TokenManager();
$_nonce = wp_create_nonce('wp_rest');

Security Fix

--- /home/deploy/wp-safety.org/data/plugin-versions/getgenie/4.4.1/getgenie.php	2026-05-23 06:13:36.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/getgenie/4.4.2/getgenie.php	2026-06-07 09:34:58.000000000 +0000
@@ -142,12 +142,26 @@
 add_action('elementor/editor/after_enqueue_scripts', 'genei_editor_script');
 add_action('elementor/editor/after_enqueue_scripts', 'genie_header_script_data');
 add_action('admin_head', 'genie_header_script_data');
-if (isset($_GET['bricks'])) {
-    add_action('wp_enqueue_scripts', 'genie_header_script_data');
-}
+add_action('wp', 'genie_register_frontend_builder_scripts');
 
-if (isset($_GET['ct_builder'])) {
-    add_action('wp_enqueue_scripts', 'genie_header_script_data');
+/**
+ * Register scripts for frontend builders like Bricks Builder and Oxygen Builder
+ * 
+ * @return void
+ */
+function genie_register_frontend_builder_scripts()
+{
+    if (!is_user_logged_in() || !current_user_can('edit_posts')) {
+        return;
+    }
+
+    if (isset($_GET['bricks'])) {
+        add_action('wp_enqueue_scripts', 'genie_header_script_data');
+    }
+
+    if (isset($_GET['ct_builder'])) {
+        add_action('wp_enqueue_scripts', 'genie_header_script_data');
+    }
 }

Exploit Outline

An unauthenticated attacker can target any public post or page on a WordPress site and append the query parameter '?bricks=1' or '?ct_builder=1' to the URL. The plugin then injects a configuration object into the page's HTML source via a script tag. By parsing this HTML, the attacker can extract a valid 'wp_rest' nonce and proprietary SEO metadata stored in post meta fields, such as keywords and competitor analysis data.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.