wpForo Forum < 3.0.2 - Missing Authorization
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:NTechnical Details
What Changed in the Fix
Changes introduced in v3.0.2
Source Code
WordPress.org SVN# 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, orwpforo_ai_refresh_rag_status(inferred from the AI RAG indexing tab logic). - Payload Parameter:
boardid(required to target a specific board context, as seen inwpforo_ai_render_rag_indexing_tab). - Authentication: Unauthenticated (accessible via `nop
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
@@ -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; @@ -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.