From 79a7916a89fca6370f5868f3cfb471c6bd2ef00f Mon Sep 17 00:00:00 2001 From: Conn Warwicker Date: Thu, 25 Jun 2026 12:22:00 +0100 Subject: [PATCH] WR490987: Fix issues identified by security audit. Fixes: S5, S10, S11. --- classes/cache_administration_helper.php | 10 +++++----- classes/cache_config.php | 15 ++++++++++++--- index.php | 3 +-- version.php | 2 +- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/classes/cache_administration_helper.php b/classes/cache_administration_helper.php index cc70646..1c418fc 100644 --- a/classes/cache_administration_helper.php +++ b/classes/cache_administration_helper.php @@ -149,7 +149,7 @@ private function generate_store_table(string $name, array $config): string { ); $table->data = []; foreach ($config['config'] as $key => $value) { - $table->data[] = [$key, $value]; + $table->data[] = [s($key), s($value)]; } $html .= html_writer::table($table); @@ -182,10 +182,10 @@ private function generate_override_table(array $overrides): string { foreach ($overrides as $definition => $items) { $itemstring = ''; foreach ($items as $setting => $value) { - $itemstring .= "{$setting}: {$value}
"; + $itemstring .= s($setting) . ": " . s($value); } - $table->data[] = [$definition, $itemstring]; + $table->data[] = [s($definition), $itemstring]; } $html .= html_writer::table($table); @@ -235,7 +235,7 @@ private function generate_mode_table(int $mode, array $config): string { // Little bit of string mangling. $conditions = ''; foreach ($ruleset['conditions'] as $condition => $value) { - $conditions .= $condition . ' = ' . $value . ', '; + $conditions .= s($condition) . ' = ' . s($value) . ', '; } $conditions = rtrim($conditions, ', '); } else { @@ -245,7 +245,7 @@ private function generate_mode_table(int $mode, array $config): string { $table->data[] = array( $counter, $conditions, - implode(',', $ruleset['stores']), + s(implode(',', $ruleset['stores'])), ); $counter++; } diff --git a/classes/cache_config.php b/classes/cache_config.php index b21e0a8..fefc037 100644 --- a/classes/cache_config.php +++ b/classes/cache_config.php @@ -223,9 +223,18 @@ private function generate_store_instance_config(array $stores): array { // Now for the derived config from the store information provided. // Manually require the cache/lib.php file to get cache classes. - $cachepath = __DIR__.'/../../../../cache/stores/' . $store['type'] . '/lib.php'; - if (!file_exists($cachepath)) { - throw new cache_exception(get_string('store_bad_type', 'tool_forcedcache', $store['type'])); + $cachepath = realpath(__DIR__ . '/../../../../cache/stores/' . basename($store['type']) . '/lib.php'); + $expectedbase = realpath(__DIR__ . '/../../../../cache/stores/'); + + // Cache path with the supplied type must still be within the expected base, to avoid fs traversal. + if ( + $cachepath === false || + strpos($cachepath, $expectedbase) !== 0 || + !file_exists($cachepath) + ) { + throw new cache_exception( + get_string('store_bad_type','tool_forcedcache', $store['type']) + ); } require_once($cachepath); $storearr['features'] = $classname::get_supported_features(); diff --git a/index.php b/index.php index 26a42ea..468962a 100644 --- a/index.php +++ b/index.php @@ -36,7 +36,6 @@ $dummy = new tool_forcedcache_cache_config(); $errors = $dummy->get_inclusion_errors(); - if (empty($CFG->alternative_cache_factory_class) || $CFG->alternative_cache_factory_class !== 'tool_forcedcache_cache_factory' || !empty($errors)) { @@ -47,7 +46,7 @@ if (!empty($errors)) { echo html_writer::tag('h3', get_string('page_config_broken', 'tool_forcedcache')); - $error = html_writer::tag('pre', $errors); + $error = html_writer::tag('pre', s($errors)); echo html_writer::tag('p', get_string('page_config_broken_details', 'tool_forcedcache', $error)); } else { echo $OUTPUT->notification(get_string('page_config_ok', 'tool_forcedcache'), \core\output\notification::NOTIFY_SUCCESS); diff --git a/version.php b/version.php index 6c9b941..07e3166 100644 --- a/version.php +++ b/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2024093000; +$plugin->version = 2024093001; $plugin->release = "2024093000"; $plugin->requires = 2024092700; // Requires 4.5. $plugin->component = 'tool_forcedcache'; // Full name of the plugin (used for diagnostics).