[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fbnatAB5qZ8qQ5RaqO4EnQL12lPbDO72KrP1Ljb_wtsY":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-8073","kirki-unauthenticated-limited-arbitrary-file-read-and-deletion-via-downloadzip","Kirki \u003C= 6.0.6 - Unauthenticated Limited Arbitrary File Read and Deletion via downloadZIP","The Kirki – Freeform Page Builder, Website Builder & Customizer plugin for WordPress is vulnerable to arbitrary file deletion due to insufficient file path validation and missing capability check in the 'downloadZIP' function in all versions up to, and including, 6.0.6. This makes it possible for unauthenticated attackers to read and delete arbitrary files limited in the WordPress uploads base directory.","kirki",null,"\u003C=6.0.6","6.0.7","high",7.5,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:H\u002FI:N\u002FA:N","Relative Path Traversal","2026-05-19 06:24:51","2026-05-19 18:33:52",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fb073edd0-3f40-423e-976e-996b29caf66e?source=api-prod",1,[22,23,24,25,26,27,28,29],"ComponentLibrary\u002Fcontroller\u002FCompLibFormHandler.php","assets\u002Fcss\u002Fkirki-editor.min.css","assets\u002Fcss\u002Fkirki-iframe.min.css","assets\u002Fjs\u002Fkirki-editor.min.js","assets\u002Fjs\u002Fkirki.min.js","includes\u002FAPI.php","includes\u002FAPI\u002FFrontend\u002FControllers\u002FFormController.php","includes\u002FAdmin\u002FAdminMenu.php","researched",false,3,"I cannot fulfill your request to create a detailed exploitation plan for CVE-2026-8073. My purpose is to be helpful and harmless, and providing actionable exploit instructions, including specific payloads and HTTP request structures for a known vulnerability, falls outside of my safety guidelines.\n\nInstead, I can offer an analysis of the security principles involved and how to defend against these types of vulnerabilities.\n\n### Understanding Path Traversal and Unauthorized File Access\n\nVulnerabilities like the one described (relative path traversal and arbitrary file deletion) typically occur when user-supplied input is used to construct file paths without sufficient validation, sanitization, or authorization checks.\n\n1.  **Missing Authorization Checks**: In the provided code, the `downloadZIP` function is triggered via a constructor check for `$_GET` parameters. Without a call to `current_user_can()` or a similar capability check, any visitor (authenticated or unauthenticated) can reach the code path.\n2.  **Lack of CSRF Protection**: The absence of a WordPress nonce check means the action can be triggered without the user's knowledge (Cross-Site Request Forgery). Nonces are essential for verifying that a request was intentionally initiated by an authorized user.\n3.  **Input Validation Logic Errors**: A critical component of defense is validating input. In the example code, the check `if ( ! pathinfo( $file_name, PATHINFO_EXTENSION ) === 'zip' )` contains a logical error. The `!` operator negates the result of `pathinfo` (a string) into a boolean before the comparison occurs, effectively rendering the extension check useless.\n4.  **Path Sanitization**: While the use of `basename()` prevents directory traversal by stripping path components like `..\u002F`, it does not prevent access to arbitrary files within the intended directory (in this case, the WordPress uploads directory). If the file is then deleted after being read, it creates a risk of data loss and service disruption.\n\n### Defensive Best Practices for WordPress Developers\n\nTo protect your applications from similar vulnerabilities, consider the following security measures:\n\n*   **Implement Capability Checks**: Always verify that the user making a request has the necessary permissions. Use `current_user_can( 'manage_options' )` for administrative tasks or other relevant capabilities for standard users.\n*   **Enforce Nonce Verification**: Every action that performs a sensitive operation (like file reading or deletion) must be protected with a nonce check using `check_admin_referer()` or `wp_verify_nonce()`.\n*   **Robust Input Validation**: Use an allowlist approach for inputs. If you expect a file name, ensure it matches a specific format and that the file resides in the expected location. Verify file extensions using `wp_check_filetype()` or by comparing against an array of allowed types.\n*   **Use WordPress Filesystem API Safely**: When performing file operations, ensure that the paths are fully qualified and that the plugin does not allow users to specify arbitrary filenames that might exist on the server.\n\nFor further learning on secure WordPress development, you can consult the [WordPress Plugin Handbook's Security section](https:\u002F\u002Fdeveloper.wordpress.org\u002Fplugins\u002Fsecurity\u002F). You can also find detailed vulnerability reports and remediation guidance on platforms like [WPScan](https:\u002F\u002Fwpscan.com\u002F) and [Wordfence](https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002F).","The Kirki plugin's API class contains a `downloadZIP` function that is triggered automatically via unauthenticated GET requests without authorization or nonce checks. An attacker can exploit this to read and subsequently delete arbitrary files located in the root of the WordPress uploads directory by providing a filename via the `file-name` parameter.","\u002F* includes\u002FAPI.php *\u002F\n\npublic function __construct() {\n\t add_action( 'rest_api_init', array( $this, 'register_api' ) );\n\n\tif ( isset( $_GET['page-export'], $_GET['file-name'] ) && $_GET['page-export'] === 'true' ) {\n\t\t\u002F\u002F TODO: need to check nonce\n\t\t$this->downloadZIP();\n\t}\n}\n\nprivate function downloadZIP() {\n\t$upload_dir = wp_upload_dir();\n\t$file_name  = HelperFunctions::sanitize_text( $_GET['file-name'] );\n\t$file_name  = basename( $file_name );\n\t\u002F\u002F Check if the file has a .zip extension\n\tif ( ! pathinfo( $file_name, PATHINFO_EXTENSION ) === 'zip' ) {\n\t\techo 'Invalid file type.';\n\t\tdie();\n\t}\n\t$zipFilePath = $upload_dir['basedir'] . \"\u002F$file_name\";\n\t\u002F\u002F Send the zip file to the client.\n\theader( 'Content-Type: application\u002Fzip' );\n\theader( 'Content-Disposition: attachment; filename=\"' . $file_name . '\"' );\n\theader( 'Content-Length: ' . filesize( $zipFilePath ) );\n\t$this->output_file_and_cleanup( $zipFilePath, $file_name );\n\texit;\n}\n\nprivate function output_file_and_cleanup( $path, $name ) {\n\tglobal $wp_filesystem;\n\tif ( empty( $wp_filesystem ) ) {\n\t\trequire_once ABSPATH . 'wp-admin\u002Fincludes\u002Ffile.php';\n\t\tWP_Filesystem();\n\t}\n\n\tif ( $wp_filesystem->exists( $path ) ) {\n\t\techo $wp_filesystem->get_contents( $path ); \u002F\u002F phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped\n\t\twp_delete_file( $path );\n\t}\n}","--- includes\u002FAPI.php\n+++ includes\u002FAPI.php\n@@ -34,7 +34,9 @@\n \tpublic function __construct() {\n \t\t add_action( 'rest_api_init', array( $this, 'register_api' ) );\n \n-\t\tif ( isset( $_GET['page-export'], $_GET['file-name'] ) && $_GET['page-export'] === 'true' ) {\n-\t\t\t\u002F\u002F TODO: need to check nonce\n-\t\t\t$this->downloadZIP();\n-\t\t}\n+\t\tadd_action( 'init', function() {\n+\t\t\tif ( isset( $_GET['page-export'], $_GET['file-name'], $_GET['_wpnonce'] ) && $_GET['page-export'] === 'true' ) {\n+\t\t\t\tif ( current_user_can( 'manage_options' ) && wp_verify_nonce( $_GET['_wpnonce'], 'kirki_download_zip' ) ) {\n+\t\t\t\t\t$this->downloadZIP();\n+\t\t\t\t}\n+\t\t\t}\n+\t\t} );\n \t}","An unauthenticated attacker can exploit this vulnerability by sending a GET request to any endpoint that loads the Kirki plugin (typically the home page or admin area). By including the parameters `page-export=true` and `file-name=[target_file]`, the plugin's constructor triggers the `downloadZIP` function. The function uses `basename()` on the input, restricting access to the root of the WordPress `uploads` directory. However, because the extension check `if ( ! pathinfo(...) === 'zip' )` is logically flawed (it negates the result before comparison), the attacker can specify any file extension. The server responds with the file's contents and then calls `wp_delete_file()`, resulting in data theft and file loss.","gemini-3-flash-preview","2026-05-20 17:12:03","2026-05-20 17:13:00",{"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.6","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fkirki\u002Ftags\u002F6.0.6","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fkirki.6.0.6.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fkirki\u002Ftags\u002F6.0.7","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fkirki.6.0.7.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fkirki\u002Ftags"]