CVE-2026-3358 Overview
The Tutor LMS – eLearning and online course solution plugin for WordPress contains an authorization bypass vulnerability that allows unauthorized enrollment in private courses. All versions up to and including 3.9.7 are affected by this flaw, which stems from missing post_status validation in the enroll_now() and course_enrollment() functions within the plugin's Course.php file.
Critical Impact
Authenticated attackers with Subscriber-level access can bypass course privacy controls and enroll in private courses, potentially exposing sensitive course information and undermining the access control model for premium or restricted educational content.
Affected Products
- Tutor LMS WordPress Plugin versions up to and including 3.9.7
- WordPress installations using vulnerable Tutor LMS plugin versions
- eLearning platforms with private course configurations
Discovery Timeline
- April 11, 2026 - CVE-2026-3358 published to NVD
- April 13, 2026 - Last updated in NVD database
Technical Details for CVE-2026-3358
Vulnerability Analysis
This vulnerability is classified as Missing Authorization (CWE-862), where the affected enrollment functions fail to properly verify access controls for private courses. While the enroll_now() and course_enrollment() functions correctly implement nonce verification, user authentication checks, and purchasability validation, they critically omit verification of the course's post_status attribute.
When a course is set to private status in WordPress, only users with the read_private_posts capability should be able to interact with or enroll in that course. However, the vulnerable functions do not check whether the target course has this protected status before processing enrollment requests.
The vulnerability allows authenticated users with minimal privileges (Subscriber-level) to craft malicious POST requests containing the course ID of a private course. Upon successful exploitation, an enrollment record is created in the database, and the private course title along with enrollment status becomes visible in the attacker's dashboard. While WordPress core access controls prevent actual content viewing (returning a 404 error), the information disclosure and unauthorized enrollment state represent a significant access control violation.
Root Cause
The root cause of this vulnerability lies in incomplete input validation within the enrollment workflow. The vulnerable code paths in Course.php (specifically at lines 134 and 2066) process enrollment requests without querying the target course's post_status field. The fix requires adding a check to ensure courses with private status are only accessible to users possessing the read_private_posts WordPress capability.
Attack Vector
The attack can be executed remotely over the network by any authenticated user with at least Subscriber-level access. The attacker must:
- Authenticate to the WordPress installation with a valid Subscriber account
- Identify or enumerate the post ID of a private course
- Craft a POST request to the enrollment endpoint with the target course ID
- Submit the request, which bypasses the missing post_status validation
The attack requires low privileges and no user interaction, making it relatively straightforward to exploit. The vulnerability exists in the enrollment API endpoints, which can be targeted through direct HTTP requests containing the appropriate nonce and course parameters.
Detection Methods for CVE-2026-3358
Indicators of Compromise
- Unexpected enrollment records in the database for private courses from users without read_private_posts capability
- Subscriber-level users appearing in enrollment lists for courses marked as private
- Unusual POST request patterns targeting enrollment endpoints with private course IDs
- Dashboard activity showing private course titles visible to unauthorized users
Detection Strategies
- Monitor enrollment database tables for records linking Subscriber accounts to private courses
- Implement logging for enrollment endpoint requests and cross-reference against course post_status values
- Audit user dashboards for display of private course information to low-privilege accounts
- Deploy web application firewall rules to flag enrollment attempts for courses with restricted visibility settings
Monitoring Recommendations
- Enable detailed access logging for all Tutor LMS enrollment API endpoints
- Set up alerts for enrollment activities involving courses with private post_status
- Periodically audit enrollment records against expected access control policies
- Review WordPress user role assignments and capability mappings related to course access
How to Mitigate CVE-2026-3358
Immediate Actions Required
- Update Tutor LMS plugin to version 3.9.8 or later immediately
- Audit existing enrollment records to identify any unauthorized private course enrollments
- Review user accounts with Subscriber-level access for suspicious enrollment activity
- Consider temporarily revoking enrollment capabilities for Subscriber users until patching is complete
Patch Information
The vulnerability has been addressed in Tutor LMS version 3.9.8. The patch changeset adds proper post_status validation to the enrollment functions, ensuring that private courses require the read_private_posts capability before enrollment is permitted. A complete version comparison between 3.9.7 and 3.9.8 is available for review. Additional technical details are available in the Wordfence vulnerability report.
Workarounds
- Restrict the default Subscriber role's enrollment capabilities at the WordPress user role level
- Use additional access control plugins to enforce course visibility based on user capabilities
- Implement server-side request filtering to validate course post_status before processing enrollment requests
- Consider temporarily setting private courses to draft status while awaiting the patch deployment
# Configuration example - WordPress capability restriction via functions.php
# Add post_status validation hook for enrollment protection
# Note: This is a temporary workaround - apply official patch for complete fix
add_filter('tutor_can_enroll_course', function($can_enroll, $course_id) {
$post_status = get_post_status($course_id);
if ($post_status === 'private' && !current_user_can('read_private_posts')) {
return false;
}
return $can_enroll;
}, 10, 2);
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

