CVE-2026-40767

wpForo Forum < 3.0.2 - Missing Authorization

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
3.0.2
Patched in
10d
Time to patch

Description

The wpForo Forum plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to 3.0.2. This makes it possible for unauthenticated attackers to perform an unauthorized action.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
None
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<3.0.2
PublishedApril 21, 2026
Last updatedApril 30, 2026
Affected pluginwpforo

What Changed in the Fix

Changes introduced in v3.0.2

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Research Plan: CVE-2026-40767 - wpForo AI Missing Authorization ## 1. Vulnerability Summary The **wpForo Forum** plugin (versions < 3.0.2) introduced Retrieval-Augmented Generation (RAG) and AI features in version 3.0.0. The vulnerability is a **Missing Authorization** flaw in several AI-related …

Show full research plan

Research Plan: CVE-2026-40767 - wpForo AI Missing Authorization

1. Vulnerability Summary

The wpForo Forum plugin (versions < 3.0.2) introduced Retrieval-Augmented Generation (RAG) and AI features in version 3.0.0. The vulnerability is a Missing Authorization flaw in several AI-related functions. Specifically, state-changing actions related to AI content indexing and status management are registered via wp_ajax_nopriv_ hooks or handled in the admin_init/init hooks without verifying if the user has the manage_options capability or a valid CSRF nonce.

This allows unauthenticated attackers to perform unauthorized actions such as triggering AI content indexing, clearing indexed embeddings, or forcing synchronization with the gVectors AI API, potentially leading to resource exhaustion or disruption of AI search/summarization features.

2. Attack Vector Analysis

  • Vulnerable Endpoint: /wp-admin/admin-ajax.php
  • AJAX Actions: wpforo_ai_index_content, wpforo_ai_clear_embeddings, or wpforo_ai_refresh_rag_status (inferred from the AI RAG indexing tab logic).
  • Payload Parameter: boardid (required to target a specific board context, as seen in wpforo_ai_render_rag_indexing_tab).
  • Authentication: Unauthenticated (accessible via `nop
Research Findings
Static analysis — not yet PoC-verified

Summary

The wpForo Forum plugin for WordPress is vulnerable to unauthorized access and information disclosure due to missing capability checks on AI-related functions and the RecentPosts widget AJAX handler. This allows unauthenticated attackers to perform unauthorized administrative actions like triggering AI content indexing or disclosing private forum posts that should be restricted.

Vulnerable Code

// widgets/RecentPosts.php line 184
// The widget fails to enforce privacy checks, allowing parameters to override visibility

            // Remove dangerous 'where' parameter
            unset( $post_args['where'] );

--- 

// widgets/RecentPosts.php lines 13-14
// Registration of unauthenticated AJAX hooks for widget loading

        add_action( 'wp_ajax_wpforo_load_ajax_widget_RecentPosts', [ $this, 'load_ajax_widget' ] );
        add_action( 'wp_ajax_nopriv_wpforo_load_ajax_widget_RecentPosts', [ $this, 'load_ajax_widget' ] );

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/wpforo/3.0.1/admin/pages/tabs/ai-features-tab-rag-indexing.php /home/deploy/wp-safety.org/data/plugin-versions/wpforo/3.0.2/admin/pages/tabs/ai-features-tab-rag-indexing.php
--- /home/deploy/wp-safety.org/data/plugin-versions/wpforo/3.0.1/admin/pages/tabs/ai-features-tab-rag-indexing.php	2026-04-07 13:25:02.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/wpforo/3.0.2/admin/pages/tabs/ai-features-tab-rag-indexing.php	2026-04-07 19:57:46.000000000 +0000
@@ -304,8 +304,16 @@
 			</div>
 			<div class="wpforo-ai-box-body">
 				<?php
-				// Get total topics count
-				$total_topics_count = WPF()->topic->get_count();
+				// Get total topics count (transient-cached, board+storage specific)
+				$_ttc_cache_key = 'wpforo_ai_ttc_' . $current_boardid . '_' . $storage_mode;
+				$total_topics_count = get_transient( $_ttc_cache_key );
+				if ( false === $total_topics_count ) {
+					$total_topics_count = (int) WPF()->db->get_var(
+						"SELECT COUNT(*) FROM `" . WPF()->tables->topics . "`"
+					);
+					set_transient( $_ttc_cache_key, $total_topics_count, 10 * MINUTE_IN_SECONDS );
+				}
+				$total_topics_count = (int) $total_topics_count;
 
 				// Get available credits from status
 				$subscription = isset( $status['subscription'] ) && is_array( $status['subscription'] ) ? $status['subscription'] : [];
@@ -509,6 +517,19 @@
 							// Get indexed counts from AI backend
 							$indexed_counts = wpforo_ai_get_indexed_counts_by_forum();
 
+							// Get all forum topic counts in a single GROUP BY query
+							// instead of calling WPF()->topic->get_count() per forum (N+1 problem)
+							$forum_topic_counts = [];
+							$_ftc_rows = WPF()->db->get_results(
+								"SELECT `forumid`, COUNT(*) as `cnt` FROM `" . WPF()->tables->topics . "` GROUP BY `forumid`",
+								ARRAY_A
+							);
+							if ( $_ftc_rows ) {
+								foreach ( $_ftc_rows as $_ftc_row ) {
+									$forum_topic_counts[ (int) $_ftc_row['forumid'] ] = (int) $_ftc_row['cnt'];
+								}
+							}
+
 							if ( ! empty( $all_forums ) ) :
 							?>
 								<div class="wpforo-ai-forum-checklist">
@@ -519,8 +540,8 @@
 										$parent_id = isset( $forum['parentid'] ) ? (int) $forum['parentid'] : 0;
 										$is_cat = isset( $forum['is_cat'] ) ? (int) $forum['is_cat'] : 0;
 
-										// Get topic count for this forum
-										$topic_count = WPF()->topic->get_count([ 'forumid' => $forum_id ]);
+										// Get topic count for this forum (from pre-fetched GROUP BY)
+										$topic_count = isset( $forum_topic_counts[ $forum_id ] ) ? $forum_topic_counts[ $forum_id ] : 0;
 
 										// Get indexed count for this forum
 										$indexed_count = isset( $indexed_counts[ $forum_id ] ) ? $indexed_counts[ $forum_id ] : 0;
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/wpforo/3.0.1/widgets/RecentPosts.php /home/deploy/wp-safety.org/data/plugin-versions/wpforo/3.0.2/widgets/RecentPosts.php
--- /home/deploy/wp-safety.org/data/plugin-versions/wpforo/3.0.1/widgets/RecentPosts.php	2026-04-07 13:25:02.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/wpforo/3.0.2/widgets/RecentPosts.php	2026-04-07 19:57:46.000000000 +0000
@@ -184,6 +184,9 @@
             // Remove dangerous 'where' parameter
             unset( $post_args['where'] );
 
+            // Force permission checks — prevents check_private=false injection
+            $post_args['check_private'] = true;
+
             // Validate 'orderby' parameter against whitelist
             if( isset( $post_args['orderby'] ) ) {

Exploit Outline

An unauthenticated attacker can exploit this vulnerability via two primary methods: 1. **Information Disclosure (RecentPosts Widget)**: Send a POST request to `/wp-admin/admin-ajax.php` with the action `wpforo_load_ajax_widget_RecentPosts`. In the payload, include an `instance` or `post_args` array containing `check_private => false`. Because the vulnerable version fails to force this value to true, the backend will return recent posts from private or restricted forums that the unauthenticated user should not be able to see. 2. **Unauthorized AI Operations**: Inferred from the AI RAG features, an attacker can target AJAX actions such as `wpforo_ai_index_content` or `wpforo_ai_clear_embeddings`. By providing a valid `boardid`, the attacker can trigger resource-heavy content indexing processes or delete existing AI vector embeddings, disrupting the forum's AI semantic search and summarization features without needing administrative credentials.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.