From 731ecda3da70f5623d59115a759ecadf894dbfa9 Mon Sep 17 00:00:00 2001 From: Ajay D'Souza Date: Tue, 3 Jun 2025 23:03:11 +0100 Subject: [PATCH 1/7] Fixed security issue --- LICENSE.txt | 0 includes/frontend/class-breadcrumbs.php | 4 ++++ includes/frontend/class-display.php | 3 +++ includes/functions.php | 6 +++++- includes/util/class-helpers.php | 28 +++++++++++++++++++++++++ includes/widgets/index.php | 0 index.php | 0 knowledgebase.php | 2 +- languages/index.php | 0 readme.txt | 7 ++++++- uninstall.php | 0 11 files changed, 47 insertions(+), 3 deletions(-) mode change 100644 => 100755 LICENSE.txt mode change 100644 => 100755 includes/widgets/index.php mode change 100644 => 100755 index.php mode change 100644 => 100755 knowledgebase.php mode change 100644 => 100755 languages/index.php mode change 100644 => 100755 readme.txt mode change 100644 => 100755 uninstall.php diff --git a/LICENSE.txt b/LICENSE.txt old mode 100644 new mode 100755 diff --git a/includes/frontend/class-breadcrumbs.php b/includes/frontend/class-breadcrumbs.php index b330070..0955dfb 100644 --- a/includes/frontend/class-breadcrumbs.php +++ b/includes/frontend/class-breadcrumbs.php @@ -7,6 +7,8 @@ namespace WebberZone\Knowledge_Base\Frontend; +use WebberZone\Knowledge_Base\Util\Helpers; + if ( ! defined( 'WPINC' ) ) { die; } @@ -50,6 +52,7 @@ public static function get_breadcrumb( $args = array() ) { // Parse incoming $args into an array and merge it with $defaults. $args = wp_parse_args( $args, $defaults ); + $args = Helpers::sanitize_args( $args ); // Convert Unicode sequence if provided. if ( strpos( $args['separator'], '\\' ) === 0 ) { @@ -139,6 +142,7 @@ private static function get_hierarchical_term_trail( \WP_Term $taxonomy, $args = ); $args = wp_parse_args( $args, $defaults ); + $args = Helpers::sanitize_args( $args ); $output = '
  • '; $output .= ''; diff --git a/includes/frontend/class-display.php b/includes/frontend/class-display.php index 08926ab..73a0e8b 100644 --- a/includes/frontend/class-display.php +++ b/includes/frontend/class-display.php @@ -8,6 +8,7 @@ namespace WebberZone\Knowledge_Base\Frontend; use WebberZone\Knowledge_Base\Util\Cache; +use WebberZone\Knowledge_Base\Util\Helpers; if ( ! defined( 'WPINC' ) ) { die; @@ -64,6 +65,7 @@ public static function get_knowledge_base( $args = array() ) { ); $args = wp_parse_args( $args, $defaults ); + $args = Helpers::sanitize_args( $args ); // Set defaults if variables are empty. $args['limit'] = ( ! empty( absint( $args['limit'] ) ) ) ? absint( $args['limit'] ) : \wzkb_get_option( 'limit' ); @@ -379,6 +381,7 @@ public static function get_categories_list( $term_id, $level = 0, $args = array( ); $args = wp_parse_args( $args, $defaults ); + $args = Helpers::sanitize_args( $args ); // Get Knowledge Base Sections. $sections = get_terms( diff --git a/includes/functions.php b/includes/functions.php index f78cc9b..a5bcfcc 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -7,6 +7,7 @@ use WebberZone\Knowledge_Base\Frontend\Media_Handler; use WebberZone\Knowledge_Base\Frontend\Related; +use WebberZone\Knowledge_Base\Util\Helpers; // If this file is called directly, abort. if ( ! defined( 'WPINC' ) ) { @@ -102,8 +103,9 @@ function wzkb_get_alert( $args = array(), $content = '' ) { // Parse incomming $args into an array and merge it with $defaults. $args = wp_parse_args( $args, $defaults ); + $args = Helpers::sanitize_args( $args ); - $type = 'wzkb-alert-' . $args['type']; + $type = 'wzkb-alert-' . sanitize_html_class( $args['type'] ); $class = implode( ' ', explode( ',', $args['class'] ) ); $class = $type . ' ' . $class; @@ -161,6 +163,7 @@ function wzkb_get_the_post_thumbnail( $args = array() ) { // Parse incomming $args into an array and merge it with $defaults. $args = wp_parse_args( $args, $defaults ); + $args = Helpers::sanitize_args( $args ); return Media_Handler::get_the_post_thumbnail( $args ); } @@ -180,6 +183,7 @@ function wzkb_related_articles( $args = array() ) { ); $args = wp_parse_args( $args, $defaults ); + $args = Helpers::sanitize_args( $args ); $related = Related::get_related_articles( $args ); diff --git a/includes/util/class-helpers.php b/includes/util/class-helpers.php index 7b6d078..9fca55c 100644 --- a/includes/util/class-helpers.php +++ b/includes/util/class-helpers.php @@ -44,4 +44,32 @@ public static function get_credit_link() { return $output; } + + /** + * Sanitize args. + * + * @since 2.3.1 + * + * @param array $args Array of arguments. + * @return array Sanitized array of arguments. + */ + public static function sanitize_args( $args ): array { + foreach ( $args as $key => $value ) { + if ( is_string( $value ) ) { + switch ( $key ) { + case 'class': + case 'className': + case 'extra_class': + $classes = explode( ' ', $value ); + $sanitized_classes = array_map( 'sanitize_html_class', $classes ); + $args[ $key ] = implode( ' ', $sanitized_classes ); + break; + default: + $args[ $key ] = wp_kses_post( $value ); + break; + } + } + } + return $args; + } } diff --git a/includes/widgets/index.php b/includes/widgets/index.php old mode 100644 new mode 100755 diff --git a/index.php b/index.php old mode 100644 new mode 100755 diff --git a/knowledgebase.php b/knowledgebase.php old mode 100644 new mode 100755 index 25857d1..6ea55d6 --- a/knowledgebase.php +++ b/knowledgebase.php @@ -13,7 +13,7 @@ * Plugin Name: WebberZone Knowledge Base * Plugin URI: https://github.com/WebberZone/knowledgebase * Description: Create a multi-product knowledge base on your WordPress site. - * Version: 2.3.0 + * Version: 2.3.1-beta1 * Author: WebberZone * Author URI: https://webberzone.com * License: GPL-2.0+ diff --git a/languages/index.php b/languages/index.php old mode 100644 new mode 100755 diff --git a/readme.txt b/readme.txt old mode 100644 new mode 100755 index a9f3e4e..8eb3529 --- a/readme.txt +++ b/readme.txt @@ -3,7 +3,7 @@ Contributors: Ajay, webberzone Donate link: https://ajaydsouza.com/donate/ Tags: knowledge base, knowledgebase, FAQ, frequently asked questions, support, documentation Requires at least: 6.3 -Tested up to: 6.7 +Tested up to: 6.8 Requires PHP: 7.4 Stable tag: 2.3.0 License: GPLv2 or later @@ -118,6 +118,11 @@ Completely rewritten. Several new features and enhancements. == Changelog == += 2.3.1 = + +* Bug fixes: + * Fixed security issue where arguments passed to the shortcodes were not properly sanitized. + = 2.3.0 = Release post: [https://webberzone.com/blog/knowledge-base-v2-3-0/](https://webberzone.com/blog/knowledge-base-v2-3-0/) diff --git a/uninstall.php b/uninstall.php old mode 100644 new mode 100755 From 7ceeb70bbaa6b05dca0824deeac8fa5d8379dd8b Mon Sep 17 00:00:00 2001 From: Ajay D'Souza Date: Tue, 3 Jun 2025 23:04:58 +0100 Subject: [PATCH 2/7] ci: update PHP versions and GitHub Actions workflow configurations --- .github/workflows/cs.yml | 4 ++-- .github/workflows/unit-tests.yml | 39 +++++++++++++++----------------- .github/workflows/zipitup.yml | 10 ++++---- 3 files changed, 25 insertions(+), 28 deletions(-) diff --git a/.github/workflows/cs.yml b/.github/workflows/cs.yml index e6ed796..39f0dc9 100644 --- a/.github/workflows/cs.yml +++ b/.github/workflows/cs.yml @@ -26,7 +26,7 @@ jobs: - name: Install PHP uses: shivammathur/setup-php@v2 with: - php-version: '7.4' + php-version: '8.0' tools: cs2pr coverage: none @@ -50,4 +50,4 @@ jobs: run: vendor/bin/phpcs --report-full --report-checkstyle=./phpcs-report.xml - name: Show PHPCS results in PR - run: cs2pr --graceful-warnings ./phpcs-report.xml + run: cs2pr --graceful-warnings ./phpcs-report.xml \ No newline at end of file diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 017a66c..ce0e304 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -23,7 +23,7 @@ jobs: matrix: # Notes regarding supported versions in WP: # The base matrix only contains the PHP versions which are supported on all supported WP versions. - php: ['8.0', '7.3', '7.4'] + php: ['8.0', '8.1', '7.4'] wp: ['latest'] experimental: [false] @@ -37,8 +37,8 @@ jobs: - php: '8.2' wp: 'latest' experimental: true - - php: '8.1' - wp: 'latest' + - php: '8.2' + wp: '6.3' experimental: true - php: '8.0' wp: '5.9' @@ -71,23 +71,18 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} - tools: phpunit-polyfills + extensions: mysqli, mysql coverage: none - # The PHP 5.6 and 7.0 images don't include mysql[i] by default. - extensions: mysqli - - - name: Set up WordPress - run: phpunit/install.sh wordpress_test root '' 127.0.0.1:3306 ${{ matrix.wp }} # On WP 5.2, PHPUnit 5.x, 6.x and 7.x are supported. # On PHP >= 8.0, PHPUnit 7.5+ is needed, no matter what. - name: Determine supported PHPUnit version id: set_phpunit run: | - if [[ "${{ matrix.php }}" > "7.4" ]]; then - echo "PHPUNIT=8.5.*" >> $GITHUB_ENV + if [[ "${{ matrix.php }}" > "8.0" ]]; then + echo "PHPUNIT=9.*" >> $GITHUB_ENV else - echo "PHPUNIT=5.7.*||6.*||7.5.*" >> $GITHUB_ENV + echo "PHPUNIT=5.7.*||6.*||7.5.*||8.5.*" >> $GITHUB_ENV fi - name: 'Composer: set up PHPUnit' @@ -99,30 +94,32 @@ jobs: # @link https://github.com/marketplace/actions/install-composer-dependencies - name: Install Composer dependencies for PHP < 8.0 if: ${{ matrix.php < 8.0 }} - uses: "ramsey/composer-install@v3" + uses: "ramsey/composer-install@v2" # For the PHP 8.0 and above, we need to install with ignore platform reqs as not all dependencies allow it yet. - name: Install Composer dependencies for PHP >= 8.0 if: ${{ matrix.php >= 8.0 }} - uses: "ramsey/composer-install@v3" + uses: "ramsey/composer-install@v2" with: composer-options: --ignore-platform-reqs - - name: 'Run Composer Update' - run: | - composer update --ignore-platform-reqs + - name: Install Subversion + run: sudo apt-get install subversion + + - name: Set up WordPress + run: phpunit/install.sh wordpress_test root '' 127.0.0.1:3306 ${{ matrix.wp }} - name: Tool versions run: | php --version composer --version - phpunit --version - which phpunit + ./vendor/bin/phpunit --version + which ./vendor/bin/phpunit - name: Run the unit tests - single site - run: vendor/bin/phpunit + run: ./vendor/bin/phpunit - name: Run the unit tests - multisite - run: vendor/bin/phpunit env: WP_MULTISITE: 1 + run: ./vendor/bin/phpunit \ No newline at end of file diff --git a/.github/workflows/zipitup.yml b/.github/workflows/zipitup.yml index ef83cfa..e4b9355 100644 --- a/.github/workflows/zipitup.yml +++ b/.github/workflows/zipitup.yml @@ -29,15 +29,15 @@ jobs: - name: Create artifact uses: montudor/action-zip@v1 with: - args: zip -X -r build/knowledgebase.zip . -x *.git* node_modules/\* .* "*/\.*" CODE_OF_CONDUCT.md CONTRIBUTING.md ISSUE_TEMPLATE.md PULL_REQUEST_TEMPLATE.md *.dist *.yml composer.* dev-helpers** build** wporg-assets** phpunit** + args: zip -X -r build/${{ github.event.repository.name }}.zip . -x *.git* node_modules/\* .* "*/\.*" CODE_OF_CONDUCT.md CONTRIBUTING.md ISSUE_TEMPLATE.md PULL_REQUEST_TEMPLATE.md *.dist *.yml *.neon composer.* package.json dev-helpers** build** wporg-assets** phpunit** - name: Upload artifact uses: actions/upload-artifact@v4 with: - name: knowledgebase - path: build/knowledgebase.zip + name: ${{ github.event.repository.name }} + path: build/${{ github.event.repository.name }}.zip - name: Upload to release uses: JasonEtco/upload-to-release@master with: - args: build/knowledgebase.zip application/zip + args: build/${{ github.event.repository.name }}.zip application/zip env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file From fffd360db2e14c08067ead5a35adbfd5aef72bb5 Mon Sep 17 00:00:00 2001 From: Ajay D'Souza Date: Tue, 3 Jun 2025 23:06:36 +0100 Subject: [PATCH 3/7] refactor: update PHPUnit bootstrap file path and simplify header docs --- phpunit/bootstrap.php | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/phpunit/bootstrap.php b/phpunit/bootstrap.php index bf54b88..8bafd6c 100644 --- a/phpunit/bootstrap.php +++ b/phpunit/bootstrap.php @@ -1,14 +1,8 @@ Date: Tue, 3 Jun 2025 23:08:27 +0100 Subject: [PATCH 4/7] chore: update composer.json with new phpunit versions and add dev scripts --- composer.json | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index bf81ab6..00601eb 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,6 @@ { "name": "webberzone/knowledgebase", "description": "Fastest way to create a highly-flexible multi-product knowledge base.", - "version": "2.3.0", "type": "wordpress-plugin", "keywords": [ "knowledge base", @@ -30,12 +29,18 @@ "dealerdirect/phpcodesniffer-composer-installer": "^1", "phpcompatibility/phpcompatibility-wp": "^2", "yoast/phpunit-polyfills": "^3", - "phpunit/phpunit": "^5.7.21 || ^6.5 || ^7.5" + "phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10 || ^11 || ^12" }, "config": { "allow-plugins": { "phpstan/extension-installer": true, "dealerdirect/phpcodesniffer-composer-installer": true } + }, + "scripts": { + "phpstan": "vendor/bin/phpstan analyse --memory-limit=2048M", + "phpstan-baseline": "vendor/bin/phpstan analyse --generate-baseline --memory-limit=2048M", + "phpcs": "vendor/bin/phpcs -p -v -s --standard=phpcs.xml.dist $(find . -name '*.php')", + "phpcbf": "vendor/bin/phpcbf -p -v -s --standard=phpcs.xml.dist $(find . -name '*.php')" } } \ No newline at end of file From 2e0352a64ad38e203eae178c53a7e3508abd7d89 Mon Sep 17 00:00:00 2001 From: Ajay D'Souza Date: Tue, 3 Jun 2025 23:46:57 +0100 Subject: [PATCH 5/7] Fixed PCP errors --- includes/admin/settings/class-settings-api.php | 14 +++++++------- includes/admin/settings/class-settings-form.php | 6 +++--- .../js/{apply-codemirror.js => apply-cm.js} | 0 .../{apply-codemirror.min.js => apply-cm.min.js} | 0 .../templates/archive-wz_knowledgebase.php | 4 +--- includes/options-api.php | 2 +- includes/widgets/class-articles-widget.php | 4 ++-- readme.txt | 2 +- 8 files changed, 15 insertions(+), 17 deletions(-) rename includes/admin/settings/js/{apply-codemirror.js => apply-cm.js} (100%) rename includes/admin/settings/js/{apply-codemirror.min.js => apply-cm.min.js} (100%) diff --git a/includes/admin/settings/class-settings-api.php b/includes/admin/settings/class-settings-api.php index 0402f7c..2ea3c71 100644 --- a/includes/admin/settings/class-settings-api.php +++ b/includes/admin/settings/class-settings-api.php @@ -252,12 +252,12 @@ public function set_translation_strings( $strings ) { // Args prefixed with an underscore are reserved for internal use. $defaults = array( 'page_header' => '', - 'reset_message' => __( 'Settings have been reset to their default values. Reload this page to view the updated settings.' ), - 'success_message' => __( 'Settings updated.' ), - 'save_changes' => __( 'Save Changes' ), - 'reset_settings' => __( 'Reset all settings' ), - 'reset_button_confirm' => __( 'Do you really want to reset all these settings to their default values?' ), - 'checkbox_modified' => __( 'Modified from default setting' ), + 'reset_message' => 'Settings have been reset to their default values. Reload this page to view the updated settings.', + 'success_message' => 'Settings updated.', + 'save_changes' => 'Save Changes', + 'reset_settings' => 'Reset all settings', + 'reset_button_confirm' => 'Do you really want to reset all these settings to their default values?', + 'checkbox_modified' => 'Modified from default setting', ); $strings = wp_parse_args( $strings, $defaults ); @@ -486,7 +486,7 @@ public function admin_enqueue_scripts( $hook ) { ); wp_register_script( 'wz-codemirror-js', - plugins_url( 'js/apply-codemirror' . $minimize . '.js', __FILE__ ), + plugins_url( 'js/apply-cm' . $minimize . '.js', __FILE__ ), array( 'jquery' ), self::VERSION, true diff --git a/includes/admin/settings/class-settings-form.php b/includes/admin/settings/class-settings-form.php index 35ddff1..e66a5f2 100644 --- a/includes/admin/settings/class-settings-form.php +++ b/includes/admin/settings/class-settings-form.php @@ -115,7 +115,7 @@ public function get_option( $option, $default_value = '' ) { */ public function callback_missing( $args ) { /* translators: 1: Code. */ - printf( esc_html__( 'The callback function used for the %1$s setting is missing.' ), '' . esc_attr( $args['id'] ) . '' ); + printf( 'The callback function used for the %1$s setting is missing.', '' . esc_attr( $args['id'] ) . '' ); } /** @@ -478,7 +478,7 @@ public function callback_thumbsizes( $args ) { $name, (int) $option['width'], (int) $option['height'], - (bool) $option['crop'] ? ' ' . __( 'cropped' ) : '' + (bool) $option['crop'] ? ' cropped' : '' ); } @@ -704,7 +704,7 @@ public function callback_file( $args ) { $value = isset( $args['value'] ) ? $args['value'] : $this->get_option( $args['id'], $args['options'] ); $size = sanitize_html_class( isset( $args['size'] ) ? $args['size'] : 'regular' ); $class = sanitize_html_class( $args['field_class'] ); - $label = isset( $args['options']['button_label'] ) ? $args['options']['button_label'] : __( 'Choose File' ); + $label = isset( $args['options']['button_label'] ) ? $args['options']['button_label'] : 'Choose File'; $html = sprintf( '', diff --git a/includes/admin/settings/js/apply-codemirror.js b/includes/admin/settings/js/apply-cm.js similarity index 100% rename from includes/admin/settings/js/apply-codemirror.js rename to includes/admin/settings/js/apply-cm.js diff --git a/includes/admin/settings/js/apply-codemirror.min.js b/includes/admin/settings/js/apply-cm.min.js similarity index 100% rename from includes/admin/settings/js/apply-codemirror.min.js rename to includes/admin/settings/js/apply-cm.min.js diff --git a/includes/frontend/templates/archive-wz_knowledgebase.php b/includes/frontend/templates/archive-wz_knowledgebase.php index a9183d4..29a60d1 100644 --- a/includes/frontend/templates/archive-wz_knowledgebase.php +++ b/includes/frontend/templates/archive-wz_knowledgebase.php @@ -34,7 +34,7 @@ // If no content, include the "No posts found" template. else : - esc_html_e( 'No results found', 'wzkb' ); + esc_html_e( 'No results found', 'knowledgebase' ); endif; ?> @@ -50,5 +50,3 @@

    diff --git a/readme.txt b/readme.txt index 8eb3529..b70face 100755 --- a/readme.txt +++ b/readme.txt @@ -1,7 +1,7 @@ === Knowledge Base === Contributors: Ajay, webberzone Donate link: https://ajaydsouza.com/donate/ -Tags: knowledge base, knowledgebase, FAQ, frequently asked questions, support, documentation +Tags: knowledge base, knowledgebase, FAQ, support, documentation Requires at least: 6.3 Tested up to: 6.8 Requires PHP: 7.4 From 5d8c09663ca0dde093059e3aeb9437ce1b2fc196 Mon Sep 17 00:00:00 2001 From: Ajay D'Souza Date: Wed, 4 Jun 2025 23:49:53 +0200 Subject: [PATCH 6/7] Updated readme --- README.md | 2 +- readme.txt | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index bb2688e..f2aa951 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ __Requires:__ 6.3 -__Tested up to:__ 6.7 +__Tested up to:__ 6.8 __License:__ [GPL-2.0+](http://www.gnu.org/licenses/gpl-2.0.html) diff --git a/readme.txt b/readme.txt index b70face..e1885b0 100755 --- a/readme.txt +++ b/readme.txt @@ -5,7 +5,7 @@ Tags: knowledge base, knowledgebase, FAQ, support, documentation Requires at least: 6.3 Tested up to: 6.8 Requires PHP: 7.4 -Stable tag: 2.3.0 +Stable tag: 2.3.1 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -113,8 +113,8 @@ You can report security bugs through the Patchstack Vulnerability Disclosure Pro == Upgrade Notice == -= 2.3.0 = -Completely rewritten. Several new features and enhancements. += 2.3.1 = +Fixed security issue where arguments passed to the shortcodes were not properly sanitized. == Changelog == From 90958bfba5e3b2d8cc8e83a43d4bb88d49bd4957 Mon Sep 17 00:00:00 2001 From: Ajay D'Souza Date: Wed, 4 Jun 2025 23:51:52 +0200 Subject: [PATCH 7/7] Security Fixes for v2.3.1 --- knowledgebase.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/knowledgebase.php b/knowledgebase.php index 6ea55d6..6c81526 100755 --- a/knowledgebase.php +++ b/knowledgebase.php @@ -13,7 +13,7 @@ * Plugin Name: WebberZone Knowledge Base * Plugin URI: https://github.com/WebberZone/knowledgebase * Description: Create a multi-product knowledge base on your WordPress site. - * Version: 2.3.1-beta1 + * Version: 2.3.1 * Author: WebberZone * Author URI: https://webberzone.com * License: GPL-2.0+ @@ -37,7 +37,7 @@ * * @var string $wzkb_version Plugin version */ - define( 'WZKB_VERSION', '2.3.0' ); + define( 'WZKB_VERSION', '2.3.1' ); } if ( ! defined( 'WZKB_PLUGIN_DIR' ) ) {