LearnPress CVE-2026-4365: Brief Summary of Unauthenticated Quiz Answer Deletion via Missing Authorization

A brief summary of CVE-2026-4365, a critical missing authorization flaw in the LearnPress WordPress plugin that allows unauthenticated attackers to delete arbitrary quiz answers using a publicly exposed nonce. Includes patch analysis and mitigation guidance.

CVE Analysis

7 min read

ZeroPath CVE Analysis
ZeroPath CVE Analysis

2026-04-13

LearnPress CVE-2026-4365: Brief Summary of Unauthenticated Quiz Answer Deletion via Missing Authorization
Experimental AI-Generated Content

This CVE analysis is an experimental publication that is completely AI-generated. The content may contain errors or inaccuracies and is subject to change as more information becomes available. We are continuously refining our process.

If you have feedback, questions, or notice any errors, please reach out to us.

[email protected]

Introduction

A missing authorization check in the LearnPress WordPress plugin allows any unauthenticated visitor to delete arbitrary quiz answer options, silently corrupting course assessments across more than 100,000 active installations. Tracked as CVE-2026-4365 with a CVSS score of 9.1, this flaw is particularly notable because the plugin itself hands attackers the only token they need: a wp_rest nonce embedded in public HTML.

LearnPress is one of the most popular open source Learning Management System (LMS) plugins for WordPress, developed by ThimPress. It powers online course creation, quizzes, and student management for educational institutions, corporate training platforms, and independent instructors worldwide. With over 100,000 active installations, vulnerabilities in LearnPress have a broad blast radius across the WordPress ecosystem.

Technical Information

The vulnerability is classified under CWE-862 (Missing Authorization) and stems from an architectural oversight where three separate components chain together to create an unauthenticated data deletion path.

The Nonce Exposure Problem

LearnPress embeds a wp_rest nonce directly into the lpData JavaScript object, which is rendered in the public frontend HTML of every page where the plugin is active. This nonce is visible to any visitor, authenticated or not. The relevant code can be found in class-lp-assets.php at line 177.

In standard WordPress security practice, nonces are meant to be paired with capability checks to provide both CSRF protection and authorization. A nonce alone does not prove a user is authorized to perform an action; it only proves the request originated from a page that WordPress rendered. By exposing this nonce publicly, LearnPress effectively neutralizes its only security gate.

The AJAX Dispatcher

The lp-load-ajax dispatcher, implemented in AbstractAjax.php at line 33, accepts incoming AJAX requests and routes them to the appropriate handler. The dispatcher validates the wp_rest nonce but performs no additional authentication or capability verification. Since the nonce is publicly available, this validation is trivially satisfied by any visitor.

The Vulnerable Action

The delete_question_answer action, found in EditQuestionAjax.php at line 285, handles the actual deletion of quiz answer options. This function contains no capability check and no ownership verification. It accepts a question answer ID and deletes it directly.

Attack Flow

The exploitation path is straightforward:

  1. An attacker visits any public page on a WordPress site running LearnPress (versions up to and including 4.3.2.8).
  2. The attacker inspects the page source or JavaScript context to extract the wp_rest nonce from the lpData object.
  3. The attacker crafts a POST request to the lp-load-ajax endpoint, specifying the delete_question_answer action and including the extracted nonce along with the target answer ID.
  4. The AJAX dispatcher validates the nonce (which passes, since it was legitimately generated by WordPress) and routes the request to the handler.
  5. The delete_question_answer function executes the deletion without checking whether the requester has any WordPress capabilities or any relationship to the question.
  6. The targeted quiz answer option is permanently removed from the database.

The following table summarizes how the three components interact:

ComponentLocationFlawSecurity Implication
lpData objectclass-lp-assets.phpExposes wp_rest nonce in public HTMLProvides attackers the required token
lp-load-ajax dispatcherAbstractAjax.phpUses nonce as the sole security gateBypasses standard authentication
delete_question_answerEditQuestionAjax.phpNo capability or ownership checkAllows arbitrary answer deletion

What makes this vulnerability especially impactful is the asymmetry between effort and damage. The attacker needs only a browser and a simple HTTP client. The damage, deletion of quiz answers, can silently corrupt assessments, invalidate student results, and undermine the integrity of entire course catalogs.

Patch Information

The vulnerability was patched in LearnPress version 4.3.3, released to the WordPress plugin repository. The fix is a surgical, single line addition inside the QuestionAnswerModel class located at inc/Models/Question/QuestionAnswerModel.php.

To understand the patch, we need to look at the pre-patch architecture. In version 4.3.2.8 and earlier, the delete() method calls check_valid_before_delete() as its gatekeeper. However, that pre-delete validation only checked two things: whether the parent question existed, and whether the question type still had the minimum number of answers. It performed no authorization check whatsoever.

Interestingly, the model class already had a check_capabilities_update() method that was properly used by the save() method for create and update operations. That method calls WordPress's user_can() to verify the current user holds the edit_lp_lesson capability for the specific question. The delete path simply never invoked it.

In version 4.3.3, the developers added a single call to $this->check_capabilities_update() inside check_valid_before_delete(), right after the question existence check and before the answer count validation:

public function check_valid_before_delete() { $questionPostModel = $this->get_question_post_model(); if ( ! $questionPostModel ) { throw new Exception( __( 'Question not found', 'learnpress' ) ); } + + $this->check_capabilities_update(); if ( $questionPostModel->get_type() === 'single_choice' || ...

The check_capabilities_update() method itself enforces the authorization:

public function check_capabilities_update() { $user = wp_get_current_user(); if ( ! user_can( $user, 'edit_' . LP_LESSON_CPT, $this->question_id ) ) { throw new Exception( __( 'You do not have permission to edit this item.', 'learnpress' ) ); } }

After the patch, when an unauthenticated attacker sends a crafted POST request to the delete_question_answer AJAX action (even with the publicly exposed wp_rest nonce), the check_capabilities_update() call retrieves the current user (which will be an anonymous visitor with no capabilities), the user_can() check fails, and an exception is thrown, halting the deletion before it ever reaches the database.

The method's PHPDoc version tag was also bumped from @version 1.0.0 to @version 1.0.1, confirming this was a targeted, intentional security fix. The elegance of this patch lies in reusing the existing check_capabilities_update() authorization method that was already protecting the save() flow. The delete path was simply an oversight that left it unguarded.

Organizations running LearnPress should update to version 4.3.3 or later immediately. The vulnerable and patched model files can be compared directly in the WordPress plugin SVN repository.

Affected Systems and Versions

All versions of the LearnPress WordPress plugin up to and including 4.3.2.8 are affected. The vulnerability is present in any WordPress installation where LearnPress is active, regardless of WordPress core version or server configuration.

The fix is available in LearnPress version 4.3.3.

Vendor Security History

ThimPress, the developer of LearnPress, has a documented pattern of security vulnerabilities in this plugin that warrants attention from organizations relying on it:

  • Authenticated SQL Injection (versions up to 4.2.6.9.3): A SQL injection vulnerability via the order parameter was accessible to users with Contributor level access. This was patched in version 4.2.6.9.4.
  • CVE-2026-4333: A stored Cross Site Scripting (XSS) vulnerability was recently identified in LearnPress, further illustrating recurring input validation and authorization gaps.

This history of authorization bypasses, injection flaws, and XSS issues suggests that organizations deploying LearnPress should maintain strict monitoring, apply updates promptly, and consider additional hardening measures such as Web Application Firewalls with WordPress specific rulesets.

References

Detect & fix
what others miss

Security magnifying glass visualization