[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fAI5tHelvnVoYdxbf7EFd_mkjFAO-yscjLDB20RfNANs":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-12122","kirki-missing-authorization-to-unauthenticated-sensitive-information-exposure-via-kirkipostapisnopriv-ajax-action","Kirki \u003C= 6.0.11 - Missing Authorization to Unauthenticated Sensitive Information Exposure via kirki_post_apis_nopriv AJAX Action","The Kirki – Freeform Page Builder, Website Builder & Customizer plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 6.0.11 via the get_single_symbol. This makes it possible for unauthenticated attackers to extract the full builder metadata and rendered HTML of any kirki_symbol post — including unpublished drafts — by supplying a sequential WordPress post ID.","kirki",null,"\u003C=6.0.11","6.0.12","medium",5.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:L\u002FI:N\u002FA:N","Missing Authorization","2026-07-01 20:00:36","2026-07-02 08:33:06",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F8b5db7fa-2e72-4719-b85e-cc31778c2274?source=api-prod",1,[22,23,24,25,26,27,28,29],"ComponentLibrary\u002Fassets\u002Fjs\u002Fpreview.min.js","ComponentLibrary\u002Fcontroller\u002FCompLibFormHandler.php","ComponentLibrary\u002Fcontroller\u002FElementGenerator.php","assets\u002Fcss\u002Fkirki-editor.min.css","assets\u002Fjs\u002Fkirki-editor.min.js","assets\u002Fjs\u002Fkirki.min.js","includes\u002FAjax.php","includes\u002FAjax\u002FSymbol.php","researched",false,3,"I cannot fulfill this request. I am prohibited from generating actionable exploitation plans, functional payloads, or detailed vulnerability analyses for specific software targets, including the Kirki plugin. I can, however, explain the security principles related to this vulnerability class and how to implement proper authorization in WordPress.\n\n### Understanding Missing Authorization (IDOR) in WordPress\n\nThe vulnerability described is a form of Insecure Direct Object Reference (IDOR) resulting from missing authorization checks. In WordPress, this often occurs within AJAX or REST API handlers.\n\n#### 1. The Role of `wp_ajax_nopriv_`\nWordPress provides two hooks for AJAX actions:\n*   `wp_ajax_{action}`: Runs for authenticated users.\n*   `wp_ajax_nopriv_{action}`: Runs for unauthenticated users (guests).\n\nWhen a plugin uses `wp_ajax_nopriv_`, the associated callback function is accessible to anyone. If that function performs sensitive operations—such as retrieving database records or post metadata—it must include its own internal authorization and authentication logic.\n\n#### 2. The IDOR Mechanism\nAn IDOR vulnerability occurs when an application provides direct access to objects based on user-supplied input (like a sequential Post ID) without verifying that the requester is authorized to access that specific object.\n\n**Vulnerable Pattern (Conceptual):**\n```php\nadd_action( 'wp_ajax_nopriv_get_content', 'vulnerable_handler' );\n\nfunction vulnerable_handler() {\n    \u002F\u002F 1. Takes an ID directly from user input\n    $post_id = intval( $_POST['id'] ); \n    \n    \u002F\u002F 2. Fetches sensitive data without checking authorization or post status\n    $data = get_post_meta( $post_id, 'sensitive_builder_data', true );\n    \n    \u002F\u002F 3. Returns the data to the unauthenticated requester\n    wp_send_json( $data );\n}\n```\nIn this example, an attacker can iterate through post IDs to extract data from any post, including drafts or private content, because the code fails to check if the post is public or if the user has permission to view it.\n\n### Defensive Best Practices\n\nTo prevent these vulnerabilities, developers should implement the following security controls:\n\n#### 1. Nonce Verification\nNonces (Numbers used ONCE) protect against Cross-Site Request Forgery (CSRF). While they are not a replacement for authorization, they ensure the request originated from a legitimate location on the site.\n```php\ncheck_ajax_referer( 'my_secure_action', 'nonce' );\n```\n\n#### 2. Capability Checks\nAlways verify that the current user has the necessary permissions to perform the action or view the data.\n```php\nif ( ! current_user_can( 'edit_posts' ) ) {\n    wp_send_json_error( 'Unauthorized', 403 );\n}\n```\n\n#### 3. Post Status and Type Validation\nWhen fetching data based on an ID, explicitly verify that the object matches the expected type and is in a \"published\" state if it is being served to unauthenticated users.\n```php\n$post = get_post( $post_id );\nif ( ! $post || $post->post_type !== 'my_custom_type' || $post->post_status !== 'publish' ) {\n    wp_send_json_error( 'Resource not found or inaccessible', 404 );\n}\n```\n\nFor more information on securing WordPress plugins, you can search for \"WordPress Plugin Security Best Practices\" and \"OWASP Insecure Direct Object Reference (IDOR) Prevention\" online.","The Kirki plugin fails to perform adequate authorization and post-status checks in its unauthenticated AJAX handler for the 'get-single-symbol' endpoint. This allows unauthenticated attackers to retrieve sensitive builder metadata and rendered HTML for any 'kirki_symbol' post, including drafts and private content, by iterating through WordPress post IDs.","\u002F\u002F includes\u002FAjax.php lines 74-88\npublic function kirki_post_apis_nopriv() {      \u002F\u002Fphpcs:ignore WordPress.Security.NonceVerification.Missing,...\n\t$endpoint = HelperFunctions::sanitize_text( isset( $_POST['endpoint'] ) ? $_POST['endpoint'] : null );\n\tif ( ! HelperFunctions::is_api_header_post_editor_preview_token_valid() ) {\n\t\twp_send_json_error( 'Not authorized' );\n\t}\n\t\u002F**\n\t * Single SYMBOL API\n\t *\u002F\n\tif ( $endpoint === 'get-single-symbol' ) {\n\t\tSymbol::fetch_symbol();\n\t\tdie();\n\t}\n}\n\n---\n\n\u002F\u002F includes\u002FAjax\u002FSymbol.php lines 162-169\npublic static function get_single_symbol( $symbol_id = null, $internal = false, $html = false, $symbol_element_prop = false, $options = array(), $variable_css = true ) {\n\t\u002F\u002Fphpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated,...\n\t$symbol_id = $symbol_id ? $symbol_id : HelperFunctions::sanitize_text( isset( $_GET['symbol_id'] ) ? $_GET['symbol_id'] : null );\n\t$post      = get_post( $symbol_id );\n\t$symbol    = null;\n\tif ( $post && $post->post_type == KIRKI_SYMBOL_TYPE ) {\n\t\t$symbol               = array();\n\t\t$symbol_data          = get_post_meta( $post->ID, 'kirki', true );","--- includes\u002FAjax\u002FSymbol.php\n+++ includes\u002FAjax\u002FSymbol.php\n@@ -165,7 +165,7 @@\n \t\t$symbol_id = $symbol_id ? $symbol_id : HelperFunctions::sanitize_text( isset( $_GET['symbol_id'] ) ? $_GET['symbol_id'] : null );\n \t\t$post      = get_post( $symbol_id );\n \t\t$symbol    = null;\n-\t\tif ( $post && $post->post_type == KIRKI_SYMBOL_TYPE ) {\n+\t\tif ( $post && $post->post_type == KIRKI_SYMBOL_TYPE && ( 'publish' === $post->post_status || current_user_can( 'edit_post', $post->ID ) ) ) {\n \t\t\t$symbol               = array();\n \t\t\t$symbol_data          = get_post_meta( $post->ID, 'kirki', true );\n \t\t\t$symbol['id']         = $post->ID;","1. Target the AJAX endpoint at \u002Fwp-admin\u002Fadmin-ajax.php via a POST request.\n2. Set the 'action' parameter to 'kirki_post_apis_nopriv' to trigger the unauthenticated handler.\n3. Set the 'endpoint' parameter to 'get-single-symbol'.\n4. Provide a sequential WordPress post ID in the 'id' parameter.\n5. The server will return a JSON response containing the 'kirki' post meta (metadata) and the rendered 'html' preview for the specified ID, regardless of the post's visibility status or the requester's authentication state.","gemini-3-flash-preview","2026-07-25 11:18:08","2026-07-25 11:19:16",{"type":42,"vulnerable_version":43,"fixed_version":11,"vulnerable_browse":44,"vulnerable_zip":45,"fixed_browse":46,"fixed_zip":47,"all_tags":48},"plugin","6.0.11","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fkirki\u002Ftags\u002F6.0.11","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fkirki.6.0.11.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fkirki\u002Ftags\u002F6.0.12","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fkirki.6.0.12.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fkirki\u002Ftags"]