From de1fa3945a798eb25d8aa36f6b3a41a8c2c0ec86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20=C3=85kerfeldt=20Wendel?= Date: Wed, 2 Sep 2026 10:12:22 +0200 Subject: [PATCH 1/4] chore: Update reference for Api Client. --- includes/eduadmin-api-phpclient | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/eduadmin-api-phpclient b/includes/eduadmin-api-phpclient index c8793e7e..e59b9456 160000 --- a/includes/eduadmin-api-phpclient +++ b/includes/eduadmin-api-phpclient @@ -1 +1 @@ -Subproject commit c8793e7e276e02aa9f1a2f96965360db6d9f2ae7 +Subproject commit e59b9456bd4a577b3917766453e45aea981e4538 From 29ed776df86d8ea81f5cc450c8d7348b21474d80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20=C3=85kerfeldt=20Wendel?= Date: Wed, 2 Sep 2026 10:19:19 +0200 Subject: [PATCH 2/4] security(API): Fixed proper filtering for OData variables to close a report from Patchstack. The issue in itself wasn't a problem, as our OData API saw that the query was incorrect and threw an error instead of leaking anything. But it's better to be safe than sorry. --- PLUGIN-CHECKSUM | 2 +- class/class-eduadmin-loginhandler.php | 2 +- .../bookingTemplate/-login-handler.php | 2 +- content/template/myPagesTemplate/bookings.php | 4 +- .../template/myPagesTemplate/certificates.php | 2 +- .../myPagesTemplate/login-tab-header.php | 2 +- includes/edu-ajax-functions.php | 6 +-- includes/edu-login-functions.php | 2 +- includes/edu-shortcodes.php | 2 +- includes/eduapi-helper-functions.php | 44 +++++++++---------- 10 files changed, 34 insertions(+), 34 deletions(-) diff --git a/PLUGIN-CHECKSUM b/PLUGIN-CHECKSUM index 18bee13f..0c3c26c1 100644 --- a/PLUGIN-CHECKSUM +++ b/PLUGIN-CHECKSUM @@ -1 +1 @@ -7728161a3a97dd741671f333b181ab1d +14059d17bedb1b0ebdb9f3cdbb4f1bc6 diff --git a/class/class-eduadmin-loginhandler.php b/class/class-eduadmin-loginhandler.php index 4dea56cd..90f4db93 100644 --- a/class/class-eduadmin-loginhandler.php +++ b/class/class-eduadmin-loginhandler.php @@ -25,7 +25,7 @@ public function process_login() { $possible_persons = EDUAPI()->OData->Persons->Search( 'PersonId', - "CanLogin and $login_field eq '" . sanitize_text_field( wp_unslash( $_POST['eduadminloginEmail'] ) ) . '\'', // Input var okay. + "CanLogin and $login_field eq " . edu_odata_quote( sanitize_text_field( wp_unslash( $_POST['eduadminloginEmail'] ) ) ), // Input var okay. 'CustomFields($filter=ShowOnWeb;)', null, null, diff --git a/content/template/bookingTemplate/-login-handler.php b/content/template/bookingTemplate/-login-handler.php index 5241887f..10f96376 100644 --- a/content/template/bookingTemplate/-login-handler.php +++ b/content/template/bookingTemplate/-login-handler.php @@ -9,7 +9,7 @@ $possible_persons = EDUAPI()->OData->Persons->Search( null, - "$login_field eq '" . sanitize_text_field( wp_unslash( $_POST['eduadminloginEmail'] ) ) . '\'', // Input var okay. + "$login_field eq " . edu_odata_quote( sanitize_text_field( wp_unslash( $_POST['eduadminloginEmail'] ) ) ), // Input var okay. 'CustomFields($filter=ShowOnWeb;)' )['value']; diff --git a/content/template/myPagesTemplate/bookings.php b/content/template/myPagesTemplate/bookings.php index 59ce48ae..09c1e75f 100644 --- a/content/template/myPagesTemplate/bookings.php +++ b/content/template/myPagesTemplate/bookings.php @@ -37,8 +37,8 @@ $events = EDUAPI()->OData->Events->Search( 'EventId,EventName,CourseName,InternalCourseName,OnDemand,StartDate,EndDate', - 'Bookings/any(b:b/Customer/CustomerId eq ' . $customer->CustomerId . ') and StatusId eq 1', - 'Bookings($expand=Participants($select=FirstName,LastName,Arrived,GradeName,Canceled,PriceNameId),UnnamedParticipants($select=PriceNameId,Quantity,Canceled);$filter=Customer/CustomerId eq ' . $customer->CustomerId . ' and NumberOfParticipants gt 0;$select=BookingId,Created,NumberOfParticipants,TotalPriceIncVat,TotalPriceExVat)' + 'Bookings/any(b:b/Customer/CustomerId eq ' . intval( $customer->CustomerId ) . ') and StatusId eq 1', + 'Bookings($expand=Participants($select=FirstName,LastName,Arrived,GradeName,Canceled,PriceNameId),UnnamedParticipants($select=PriceNameId,Quantity,Canceled);$filter=Customer/CustomerId eq ' . intval( $customer->CustomerId ) . ' and NumberOfParticipants gt 0;$select=BookingId,Created,NumberOfParticipants,TotalPriceIncVat,TotalPriceExVat)' ); $bookings = array(); diff --git a/content/template/myPagesTemplate/certificates.php b/content/template/myPagesTemplate/certificates.php index 9b4bd00e..aec4c4fc 100644 --- a/content/template/myPagesTemplate/certificates.php +++ b/content/template/myPagesTemplate/certificates.php @@ -10,7 +10,7 @@ if ( $show_company_certificates ) { $certificates = EDUAPI()->OData->Persons->Search( 'PersonId,FirstName,LastName,CivicRegistrationNumber', - 'CustomerId eq ' . $customer->CustomerId, + 'CustomerId eq ' . intval( $customer->CustomerId ), 'Certificates' )["value"]; } else { diff --git a/content/template/myPagesTemplate/login-tab-header.php b/content/template/myPagesTemplate/login-tab-header.php index 30732c21..6b934597 100644 --- a/content/template/myPagesTemplate/login-tab-header.php +++ b/content/template/myPagesTemplate/login-tab-header.php @@ -15,7 +15,7 @@ if ( $show_company_certificates ) { $certificates = EDUAPI()->OData->Persons->Search( 'PersonId,FirstName,LastName,CivicRegistrationNumber', - 'CustomerId eq ' . $customer->CustomerId, + 'CustomerId eq ' . intval( $customer->CustomerId ), 'Certificates' )["value"]; } else { diff --git a/includes/edu-ajax-functions.php b/includes/edu-ajax-functions.php index 1f35b8e9..2f33feb8 100644 --- a/includes/edu-ajax-functions.php +++ b/includes/edu-ajax-functions.php @@ -43,9 +43,9 @@ function edu_listview_courselist() { } if ( ! empty( $category_id ) && ! edu_starts_with( $category_id, 'deep-' ) ) { - $filters[] = 'CategoryId eq ' . $category_id; + $filters[] = 'CategoryId eq ' . intval( $category_id ); } elseif ( ! empty( $category_id ) && edu_starts_with( $category_id, 'deep-' ) ) { - $filters[] = 'Categories/any(c:c/CategoryId eq ' . str_replace( 'deep-', '', $category_id ) . ')'; + $filters[] = 'Categories/any(c:c/CategoryId eq ' . intval( str_replace( 'deep-', '', $category_id ) ) . ')'; } if ( ! empty( $_POST['city'] ) && is_numeric( $_POST['city'] ) ) { @@ -53,7 +53,7 @@ function edu_listview_courselist() { } if ( ! empty( $_POST['subject'] ) ) { - $filters[] = 'Subjects/any(s:s/SubjectName eq \'' . sanitize_text_field( $_POST['subject'] ) . '\')'; + $filters[] = 'Subjects/any(s:s/SubjectName eq ' . edu_odata_quote( sanitize_text_field( wp_unslash( $_POST['subject'] ) ) ) . ')'; } if ( ! empty( $_POST['subjectid'] ) ) { diff --git a/includes/edu-login-functions.php b/includes/edu-login-functions.php index 96d15ea5..446db62f 100644 --- a/includes/edu-login-functions.php +++ b/includes/edu-login-functions.php @@ -7,7 +7,7 @@ function edu_send_forgotten_password( $login_value ) { $cc = EDUAPI()->OData->Persons->Search( null, - "$login_field eq '" . sanitize_text_field( $login_value ) . '\' and CanLogin', + "$login_field eq " . edu_odata_quote( sanitize_text_field( wp_unslash( $login_value ) ) ) . ' and CanLogin', null, null, null, diff --git a/includes/edu-shortcodes.php b/includes/edu-shortcodes.php index 353e6682..264e600f 100644 --- a/includes/edu-shortcodes.php +++ b/includes/edu-shortcodes.php @@ -871,7 +871,7 @@ function eduadmin_get_programme_list( $attributes ) { $programmes = EDUAPI()->OData->Programmes->Search( null, 'ShowOnWeb' . - ( ! empty( $attributes['category'] ) ? ' and CategoryId eq ' . $attributes['category'] : '' ), + ( ! empty( $attributes['category'] ) ? ' and CategoryId eq ' . intval( $attributes['category'] ) : '' ), 'ProgrammeStarts(' . '$filter=' . 'HasPublicPriceName' . diff --git a/includes/eduapi-helper-functions.php b/includes/eduapi-helper-functions.php index 25a232ec..bdb628c1 100644 --- a/includes/eduapi-helper-functions.php +++ b/includes/eduapi-helper-functions.php @@ -196,9 +196,9 @@ public function GetCourseList( $attributes, $category_id, $city, $subjectid, $co $filters[] = 'OnDemand eq false'; if ( ! empty( $category_id ) && ! edu_starts_with( $category_id, 'deep-' ) ) { - $filters[] = 'CategoryId eq ' . $category_id; + $filters[] = 'CategoryId eq ' . intval( $category_id ); } elseif ( ! empty( $category_id ) && edu_starts_with( $category_id, 'deep-' ) ) { - $filters[] = 'Categories/any(c:c/CategoryId eq ' . str_replace( 'deep-', '', $category_id ) . ')'; + $filters[] = 'Categories/any(c:c/CategoryId eq ' . intval( str_replace( 'deep-', '', $category_id ) ) . ')'; } if ( ! empty( $city ) ) { @@ -206,16 +206,16 @@ public function GetCourseList( $attributes, $category_id, $city, $subjectid, $co } if ( isset( $attributes['subject'] ) && ! empty( $attributes['subject'] ) ) { - $filters[] = 'Subjects/any(s:s/SubjectName eq \'' . sanitize_text_field( $attributes['subject'] ) . '\')'; + $filters[] = 'Subjects/any(s:s/SubjectName eq ' . edu_odata_quote( sanitize_text_field( wp_unslash( $attributes['subject'] ) ) ) . ')'; } if ( ! empty( $subjectid ) ) { - $filters[] = 'Subjects/any(s:s/SubjectId eq ' . $subjectid . ')'; + $filters[] = 'Subjects/any(s:s/SubjectId eq ' . intval( $subjectid ) . ')'; $attributes['subjectid'] = $subjectid; } if ( ! empty( $courselevel ) ) { - $filters[] = 'CourseLevelId eq ' . $courselevel; + $filters[] = 'CourseLevelId eq ' . intval( $courselevel ); } $sort_order = EDU()->get_option( 'eduadmin-listSortOrder', 'SortIndex' ); @@ -311,9 +311,9 @@ public function GetOnDemandCourseList( $attributes, $category_id, $city, $subjec $filters[] = 'OnDemand eq true'; if ( ! empty( $category_id ) && ! edu_starts_with( $category_id, 'deep-' ) ) { - $filters[] = 'CategoryId eq ' . $category_id; + $filters[] = 'CategoryId eq ' . intval( $category_id ); } elseif ( ! empty( $category_id ) && edu_starts_with( $category_id, 'deep-' ) ) { - $filters[] = 'Categories/any(c:c/CategoryId eq ' . str_replace( 'deep-', '', $category_id ) . ')'; + $filters[] = 'Categories/any(c:c/CategoryId eq ' . intval( str_replace( 'deep-', '', $category_id ) ) . ')'; } if ( ! empty( $city ) ) { @@ -321,16 +321,16 @@ public function GetOnDemandCourseList( $attributes, $category_id, $city, $subjec } if ( isset( $attributes['subject'] ) && ! empty( $attributes['subject'] ) ) { - $filters[] = 'Subjects/any(s:s/SubjectName eq \'' . sanitize_text_field( $attributes['subject'] ) . '\')'; + $filters[] = 'Subjects/any(s:s/SubjectName eq ' . edu_odata_quote( sanitize_text_field( wp_unslash( $attributes['subject'] ) ) ) . ')'; } if ( ! empty( $subjectid ) ) { - $filters[] = 'Subjects/any(s:s/SubjectId eq ' . $subjectid . ')'; + $filters[] = 'Subjects/any(s:s/SubjectId eq ' . intval( $subjectid ) . ')'; $attributes['subjectid'] = $subjectid; } if ( ! empty( $courselevel ) ) { - $filters[] = 'CourseLevelId eq ' . $courselevel; + $filters[] = 'CourseLevelId eq ' . intval( $courselevel ); } $sort_order = EDU()->get_option( 'eduadmin-listSortOrder', 'SortIndex' ); @@ -424,9 +424,9 @@ public function GetEventList( $attributes, $category_id, $city, $subjectid, $cou $filters[] = 'ShowOnWeb'; if ( ! empty( $category_id ) && ! edu_starts_with( $category_id, 'deep-' ) ) { - $filters[] = 'CategoryId eq ' . $category_id; + $filters[] = 'CategoryId eq ' . intval( $category_id ); } elseif ( ! empty( $category_id ) && edu_starts_with( $category_id, 'deep-' ) ) { - $filters[] = 'Categories/any(c:c/CategoryId eq ' . str_replace( 'deep-', '', $category_id ) . ')'; + $filters[] = 'Categories/any(c:c/CategoryId eq ' . intval( str_replace( 'deep-', '', $category_id ) ) . ')'; } if ( ! empty( $city ) ) { @@ -434,16 +434,16 @@ public function GetEventList( $attributes, $category_id, $city, $subjectid, $cou } if ( isset( $attributes['subject'] ) && ! empty( $attributes['subject'] ) ) { - $filters[] = 'Subjects/any(s:s/SubjectName eq \'' . sanitize_text_field( $attributes['subject'] ) . '\')'; + $filters[] = 'Subjects/any(s:s/SubjectName eq ' . edu_odata_quote( sanitize_text_field( wp_unslash( $attributes['subject'] ) ) ) . ')'; } if ( ! empty( $subjectid ) ) { - $filters[] = 'Subjects/any(s:s/SubjectId eq ' . $subjectid . ')'; - $attributes['subjectid'] = $subjectid; + $filters[] = 'Subjects/any(s:s/SubjectId eq ' . intval( $subjectid ) . ')'; + $attributes['subjectid'] = intval( $subjectid ); } if ( ! empty( $courselevel ) ) { - $filters[] = 'CourseLevelId eq ' . $courselevel; + $filters[] = 'CourseLevelId eq ' . intval( $courselevel ); } $order_by = array(); @@ -539,9 +539,9 @@ public function GetOnDemandEventList( $attributes, $category_id, $city, $subject $filters[] = 'OnDemand'; if ( ! empty( $category_id ) && ! edu_starts_with( $category_id, 'deep-' ) ) { - $filters[] = 'CategoryId eq ' . $category_id; + $filters[] = 'CategoryId eq ' . intval( $category_id ); } elseif ( ! empty( $category_id ) && edu_starts_with( $category_id, 'deep-' ) ) { - $filters[] = 'Categories/any(c:c/CategoryId eq ' . str_replace( 'deep-', '', $category_id ) . ')'; + $filters[] = 'Categories/any(c:c/CategoryId eq ' . intval( str_replace( 'deep-', '', $category_id ) ) . ')'; } if ( ! empty( $city ) ) { @@ -549,16 +549,16 @@ public function GetOnDemandEventList( $attributes, $category_id, $city, $subject } if ( isset( $attributes['subject'] ) && ! empty( $attributes['subject'] ) ) { - $filters[] = 'Subjects/any(s:s/SubjectName eq \'' . sanitize_text_field( $attributes['subject'] ) . '\')'; + $filters[] = 'Subjects/any(s:s/SubjectName eq ' . edu_odata_quote( sanitize_text_field( wp_unslash( $attributes['subject'] ) ) ) . ')'; } if ( ! empty( $subjectid ) ) { - $filters[] = 'Subjects/any(s:s/SubjectId eq ' . $subjectid . ')'; - $attributes['subjectid'] = $subjectid; + $filters[] = 'Subjects/any(s:s/SubjectId eq ' . intval( $subjectid ) . ')'; + $attributes['subjectid'] = intval( $subjectid ); } if ( ! empty( $courselevel ) ) { - $filters[] = 'CourseLevelId eq ' . $courselevel; + $filters[] = 'CourseLevelId eq ' . intval( $courselevel ); } $order_by = array(); From 180652b3f8920c7d75e4e62ab6ab3ca9739095b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20=C3=85kerfeldt=20Wendel?= Date: Wed, 2 Sep 2026 10:32:13 +0200 Subject: [PATCH 3/4] chore(release): 5.4.3 --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bbaad6da..4a7ff559 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [5.4.3](https://github.com/MultinetInteractive/EduAdmin-WordPress/compare/v5.4.2...v5.4.3) (2026-09-02) + + +### Security + +* **API:** Fixed proper filtering for OData variables to close a report from Patchstack. ([29ed776](https://github.com/MultinetInteractive/EduAdmin-WordPress/commit/29ed776df86d8ea81f5cc450c8d7348b21474d80)) + ### [5.4.2](https://github.com/MultinetInteractive/EduAdmin-WordPress/compare/v5.4.0...v5.4.2) (2026-04-30) diff --git a/package.json b/package.json index f603d3f3..74372e35 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "eduadmin-wordpress-plugin", "private": true, - "version": "5.4.2", + "version": "5.4.3", "repository": "https://github.com/MultinetInteractive/EduAdmin-WordPress.git", "author": "Chris GÄrdenberg ", "license": "MIT", From f47a8369bdf5c0e12909beda7c2ab14ac01bd5eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20=C3=85kerfeldt=20Wendel?= Date: Wed, 2 Sep 2026 10:32:16 +0200 Subject: [PATCH 4/4] chore: versionbump --- PLUGIN-CHECKSUM | 2 +- eduadmin.php | 2 +- readme.md | 16 ++++++++-------- readme.txt | 16 ++++++++-------- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/PLUGIN-CHECKSUM b/PLUGIN-CHECKSUM index 0c3c26c1..a0a59d12 100644 --- a/PLUGIN-CHECKSUM +++ b/PLUGIN-CHECKSUM @@ -1 +1 @@ -14059d17bedb1b0ebdb9f3cdbb4f1bc6 +e0c928c4d26838ef036a5067b4f081b4 diff --git a/eduadmin.php b/eduadmin.php index 6cc54523..11d753af 100644 --- a/eduadmin.php +++ b/eduadmin.php @@ -9,7 +9,7 @@ * Plugin URI: https://www.eduadmin.com * Description: EduAdmin plugin to allow visitors to book courses at your website * Tags: booking, participants, courses, events, eduadmin - * Version: 5.4.2 + * Version: 5.4.3 * GitHub Plugin URI: multinetinteractive/eduadmin-wordpress * GitHub Plugin URI: https://github.com/multinetinteractive/eduadmin-wordpress * Requires at least: 6.0 diff --git a/readme.md b/readme.md index 9b8ba2a7..f5cbed94 100644 --- a/readme.md +++ b/readme.md @@ -1,7 +1,7 @@ # EduAdmin Booking - Requires at least: 6.0 - Tested up to: 7.0 -- Stable tag: 5.4.2 +- Stable tag: 5.4.3 - Requires PHP: 8.1 - License: GPL3 - License URI: https://www.gnu.org/licenses/gpl-3.0.en.html @@ -44,6 +44,13 @@ If you notice that your API key doesn't work any more, you have to contact us. The full changelog available on [GitHub](https://github.com/MultinetInteractive/EduAdmin-WordPress/blob/production/CHANGELOG.md) +### [5.4.3](https://github.com/MultinetInteractive/EduAdmin-WordPress/compare/v5.4.2...v5.4.3) (2026-09-02) + + +#### Security + +* **API:** Fixed proper filtering for OData variables to close a report from Patchstack. ([29ed776](https://github.com/MultinetInteractive/EduAdmin-WordPress/commit/29ed776df86d8ea81f5cc450c8d7348b21474d80)) + ### [5.4.2](https://github.com/MultinetInteractive/EduAdmin-WordPress/compare/v5.4.0...v5.4.2) (2026-04-30) @@ -75,12 +82,5 @@ The full changelog available on [GitHub](https://github.com/MultinetInteractive/ * Remove ondemand-attribute from detailinfo ([dfa3f59](https://github.com/MultinetInteractive/EduAdmin-WordPress/commit/dfa3f59c5bea11c8da99d5067e415d6859475a34)) -### [5.3.1](https://github.com/MultinetInteractive/EduAdmin-WordPress/compare/v5.3.0...v5.3.1) (2024-11-05) - - -#### Bug Fixes - -* Set health-check as blocking, so we get an actual result, increase timeout to 0.5 seconds ([7e4bd4e](https://github.com/MultinetInteractive/EduAdmin-WordPress/commit/7e4bd4e7ece1efe0bd7e99ecc5b0ada8f7422957)) - diff --git a/readme.txt b/readme.txt index 20035d71..2347194e 100644 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ Contributors: mnchga Tags: booking, participants, courses, events, eduadmin Requires at least: 6.0 Tested up to: 7.0 -Stable tag: 5.4.2 +Stable tag: 5.4.3 Requires PHP: 8.1 License: GPL3 License URI: https://www.gnu.org/licenses/gpl-3.0.en.html @@ -49,6 +49,13 @@ If you notice that your API key doesn't work any more, you have to contact us. The full changelog available on [GitHub](https://github.com/MultinetInteractive/EduAdmin-WordPress/blob/production/CHANGELOG.md) +### [5.4.3](https://github.com/MultinetInteractive/EduAdmin-WordPress/compare/v5.4.2...v5.4.3) (2026-09-02) + + +#### Security + +* **API:** Fixed proper filtering for OData variables to close a report from Patchstack. ([29ed776](https://github.com/MultinetInteractive/EduAdmin-WordPress/commit/29ed776df86d8ea81f5cc450c8d7348b21474d80)) + ### [5.4.2](https://github.com/MultinetInteractive/EduAdmin-WordPress/compare/v5.4.0...v5.4.2) (2026-04-30) @@ -80,12 +87,5 @@ The full changelog available on [GitHub](https://github.com/MultinetInteractive/ * Remove ondemand-attribute from detailinfo ([dfa3f59](https://github.com/MultinetInteractive/EduAdmin-WordPress/commit/dfa3f59c5bea11c8da99d5067e415d6859475a34)) -### [5.3.1](https://github.com/MultinetInteractive/EduAdmin-WordPress/compare/v5.3.0...v5.3.1) (2024-11-05) - - -#### Bug Fixes - -* Set health-check as blocking, so we get an actual result, increase timeout to 0.5 seconds ([7e4bd4e](https://github.com/MultinetInteractive/EduAdmin-WordPress/commit/7e4bd4e7ece1efe0bd7e99ecc5b0ada8f7422957)) -