REPORT / 01

Analysis Report · Folder Analysis cache/tutor_3.9.2 → cache/tutor_3.9.4 — CVE-2025-13935

Shared security patch analysis results

mode patchdiff ai claude_cli haiku
02 · Lifecycle actions cancel · resume · skip · regenerate
03 · Share this analysis copy link · embed report
03 · CVE Security Analysis & Writeups ai-generated · per cve

Comprehensive security analysis generated by AI for each confirmed CVE match. Click on a CVE to view the detailed writeup including vulnerability background, technical details, patch analysis, and PoC guide.

CVE-2025-13935 NVD
AI-Generated Analysis
05 · Findings filter · search · paginate
Use quotes for exact: "SQL injection" · Operators: hello AND bye, admin OR root, -error, NOT warning
Showing 0 to 0 of 0 results
classes/Course.php AI: 2 vulnerabilities 2 true positives CVE-2025-13935
--- cache/tutor_3.9.2/classes/Course.php	2026-01-09 00:37:03.808520625 +0000+++ cache/tutor_3.9.4/classes/Course.php	2026-01-09 00:38:24.081403085 +0000@@ -2119,12 +2119,17 @@ 			die( esc_html__( 'Please Sign-In', 'tutor' ) ); 		} +		if ( ! tutor_utils()->is_enrolled( $course_id, $user_id ) ) {+			die( esc_html__( 'User is not enrolled in course', 'tutor' ) );+		}+ 		/** 		 * Filter hook provided to restrict course completion. This is useful 		 * for specific cases like prerequisites. WP_Error should be returned 		 * from the filter value to prevent the completion. 		 */ 		$can_complete = apply_filters( 'tutor_user_can_complete_course', true, $user_id, $course_id );+ 		if ( is_wp_error( $can_complete ) ) { 			tutor_utils()->redirect_to( $permalink, $can_complete->get_error_message(), 'error' ); 		} else {@@ -2992,6 +2997,25 @@ 			if ( $password_protected ) { 				wp_send_json_error( __( 'This course is password protected', 'tutor' ) ); 			}++			/**+			 * This check was added to address a security issue where users could+			 * enroll in a course via an AJAX call without purchasing it.+			 *+			 * To prevent this, we now verify whether the course is paid.+			 * Additionally, we check if the user is already enrolled, since+			 * Tutor's default behavior enrolls users automatically upon purchase.+			 *+			 * @since 3.9.4+			 */+			if ( tutor_utils()->is_course_purchasable( $course_id ) ) {+				$is_enrolled = (bool) tutor_utils()->is_enrolled( $course_id, $user_id );++				if ( ! $is_enrolled ) {+					wp_send_json_error( __( 'Please purchase the course before enrolling', 'tutor' ) );+				}+			}+ 			$enroll = tutor_utils()->do_enroll( $course_id, 0, $user_id ); 			if ( $enroll ) { 				wp_send_json_success( __( 'Enrollment successfully done!', 'tutor' ) );
AI Analysis
Vulnerability Existed: yes
TRUE POSITIVE
Improper Access Control - CWE-284 - classes/Course.php Lines 2122-2124
[Old Code]
No enrollment check present before allowing course completion
[Fixed Code]
```php
if ( ! tutor_utils()->is_enrolled( $course_id, $user_id ) ) {
    die( esc_html__( 'User is not enrolled in course', 'tutor' ) );
}
```
Explanation:
The original code allowed users to mark a course as complete without verifying enrollment status. An authenticated user could directly call the course completion function with any course_id and user_id to mark completion, even if not enrolled. The fix adds an enrollment check before allowing course completion, properly enforcing access control.

---

Vulnerability Existed: yes
TRUE POSITIVE
Improper Access Control - CWE-284 - classes/Course.php Lines 3011-3019
[Old Code]
```php
$enroll = tutor_utils()->do_enroll( $course_id, 0, $user_id );
if ( $enroll ) {
    wp_send_json_success( __( 'Enrollment successfully done!', 'tutor' ) );
}
```
[Fixed Code]
```php
if ( tutor_utils()->is_course_purchasable( $course_id ) ) {
    $is_enrolled = (bool) tutor_utils()->is_enrolled( $course_id, $user_id );
    
    if ( ! $is_enrolled ) {
        wp_send_json_error( __( 'Please purchase the course before enrolling', 'tutor' ) );
    }
}

$enroll = tutor_utils()->do_enroll( $course_id, 0, $user_id );
```
Explanation:
The original AJAX enrollment endpoint allowed users to enroll in paid courses without purchasing them. An attacker could call this endpoint directly to gain course access. The fix checks if the course is purchasable and verifies the user has already purchased/enrolled before allowing enrollment via AJAX, preventing unauthorized course access.
CVE Analysis Results:
CVE-2025-13935: Yes
View CVE Description
The Tutor LMS – eLearning and online course solution plugin for WordPress is vulnerable to unauthorized course completion in all versions up to, and including, 3.9.2. This is due to missing enrollment verification in the 'mark_course_complete' function. This makes it possible for authenticated attackers, with subscriber level access and above, to mark any course as completed.
Showing 1 to 1 of 1 results