diff --git a/CHANGELOG.md b/CHANGELOG.md index cca53588..b68dd19c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## v0.12.11 - 2023-12-18 + +### Fixed + +- Allow Windows drive paths. + ## v0.12.10 - 2023-11-27 ### Changed diff --git a/src/mantle/assets/class-asset-loader.php b/src/mantle/assets/class-asset-loader.php index a98dc6d5..6d5c3897 100644 --- a/src/mantle/assets/class-asset-loader.php +++ b/src/mantle/assets/class-asset-loader.php @@ -13,6 +13,7 @@ use Symfony\Component\Finder\SplFileInfo; use function Mantle\Support\Helpers\collect; +use function Mantle\Support\Helpers\validate_file; /** * Mantle Asset Loader diff --git a/src/mantle/assets/class-asset-service-provider.php b/src/mantle/assets/class-asset-service-provider.php index 3cd5bd01..82f12e2c 100644 --- a/src/mantle/assets/class-asset-service-provider.php +++ b/src/mantle/assets/class-asset-service-provider.php @@ -9,6 +9,8 @@ use Mantle\Support\Service_Provider; +use function Mantle\Support\Helpers\validate_file; + /** * Asset Service Provider */ diff --git a/src/mantle/database/model/concerns/trait-has-events.php b/src/mantle/database/model/concerns/trait-has-events.php index b611b32a..48bf1588 100644 --- a/src/mantle/database/model/concerns/trait-has-events.php +++ b/src/mantle/database/model/concerns/trait-has-events.php @@ -3,6 +3,7 @@ * Has_Events class file. * * @package Mantle + * * @phpcs:disable WordPressVIPMinimum.Variables.VariableAnalysis.StaticOutsideClass */ diff --git a/src/mantle/database/model/concerns/trait-has-global-scopes.php b/src/mantle/database/model/concerns/trait-has-global-scopes.php index 30f9a18f..b9b8cae6 100644 --- a/src/mantle/database/model/concerns/trait-has-global-scopes.php +++ b/src/mantle/database/model/concerns/trait-has-global-scopes.php @@ -3,6 +3,7 @@ * Has_Global_Scopes class file. * * @package Mantle + * * @phpcs:disable WordPressVIPMinimum.Variables.VariableAnalysis.StaticOutsideClass */ diff --git a/src/mantle/database/model/registration/trait-register-meta.php b/src/mantle/database/model/registration/trait-register-meta.php index ed75c8f8..f61b2b8d 100644 --- a/src/mantle/database/model/registration/trait-register-meta.php +++ b/src/mantle/database/model/registration/trait-register-meta.php @@ -3,6 +3,7 @@ * Register_Meta trait file. * * @package Mantle + * * @phpcs:disable WordPressVIPMinimum.Variables.VariableAnalysis.StaticOutsideClass */ diff --git a/src/mantle/database/model/registration/trait-register-rest-fields.php b/src/mantle/database/model/registration/trait-register-rest-fields.php index 59d6e52a..e8359d72 100644 --- a/src/mantle/database/model/registration/trait-register-rest-fields.php +++ b/src/mantle/database/model/registration/trait-register-rest-fields.php @@ -3,6 +3,7 @@ * Register_Post_Type trait file. * * @package Mantle + * * @phpcs:disable WordPressVIPMinimum.Variables.VariableAnalysis.StaticOutsideClass */ diff --git a/src/mantle/database/query/class-post-query-builder.php b/src/mantle/database/query/class-post-query-builder.php index c5ad15ae..f49520d6 100644 --- a/src/mantle/database/query/class-post-query-builder.php +++ b/src/mantle/database/query/class-post-query-builder.php @@ -3,6 +3,7 @@ * Post_Query_Builder class file. * * @package Mantle + * * @phpcs:disable Squiz.Commenting.FunctionComment */ diff --git a/src/mantle/framework/helpers.php b/src/mantle/framework/helpers.php index 8a7aea0c..45b152e2 100644 --- a/src/mantle/framework/helpers.php +++ b/src/mantle/framework/helpers.php @@ -8,6 +8,7 @@ * @deprecated Deprecated in favor of package-specific helpers. * * @package Mantle + * * @phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound, Squiz.Commenting.FunctionComment */ diff --git a/src/mantle/http/class-request.php b/src/mantle/http/class-request.php index 5a536e3c..d647be6c 100644 --- a/src/mantle/http/class-request.php +++ b/src/mantle/http/class-request.php @@ -3,6 +3,7 @@ * Request class file. * * @package Mantle + * * @phpcs:disable Squiz.Commenting.FunctionComment.MissingParamComment */ diff --git a/src/mantle/http/class-uploaded-file.php b/src/mantle/http/class-uploaded-file.php index 580aab77..6eec1c27 100644 --- a/src/mantle/http/class-uploaded-file.php +++ b/src/mantle/http/class-uploaded-file.php @@ -3,6 +3,7 @@ * Uploaded_File class file. * * @package Mantle + * * @phpcs:disable Squiz.Commenting.FunctionComment.MissingParamComment */ diff --git a/src/mantle/http/view/class-view-finder.php b/src/mantle/http/view/class-view-finder.php index 1fadcb74..32c6d451 100644 --- a/src/mantle/http/view/class-view-finder.php +++ b/src/mantle/http/view/class-view-finder.php @@ -3,6 +3,7 @@ * View_Finder class file. * * @package Mantle + * * @phpcs:disable WordPress.WP.DiscouragedConstants */ diff --git a/src/mantle/http/view/class-view.php b/src/mantle/http/view/class-view.php index 6a016bd2..b536e2f9 100644 --- a/src/mantle/http/view/class-view.php +++ b/src/mantle/http/view/class-view.php @@ -3,6 +3,7 @@ * View class file. * * @package Mantle + * * @phpcs:disable WordPress.WP.GlobalVariablesOverride.Prohibited */ diff --git a/src/mantle/scheduling/class-event.php b/src/mantle/scheduling/class-event.php index 8bbfffaa..602c24b5 100644 --- a/src/mantle/scheduling/class-event.php +++ b/src/mantle/scheduling/class-event.php @@ -3,6 +3,7 @@ * Event class file. * * @package Mantle + * * @phpcs:disable WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid */ diff --git a/src/mantle/scheduling/class-schedule.php b/src/mantle/scheduling/class-schedule.php index 88897fb2..b5c1fa7c 100644 --- a/src/mantle/scheduling/class-schedule.php +++ b/src/mantle/scheduling/class-schedule.php @@ -3,6 +3,7 @@ * Schedule class file. * * @package Mantle + * * @phpcs:disable WordPress.NamingConventions.ValidVariableName.PropertyNotSnakeCase */ diff --git a/src/mantle/scheduling/trait-manages-frequencies.php b/src/mantle/scheduling/trait-manages-frequencies.php index 747f670b..51f81d3b 100644 --- a/src/mantle/scheduling/trait-manages-frequencies.php +++ b/src/mantle/scheduling/trait-manages-frequencies.php @@ -3,6 +3,7 @@ * Manages_Frequencies trait file. * * @package Mantle + * * @phpcs:disable WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid */ diff --git a/src/mantle/support/class-arr.php b/src/mantle/support/class-arr.php index 9614a77b..543ba4ab 100644 --- a/src/mantle/support/class-arr.php +++ b/src/mantle/support/class-arr.php @@ -3,6 +3,7 @@ * Arr class file. * * @package Mantle + * * phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.VariableRedeclaration */ diff --git a/src/mantle/support/helpers/helpers-general.php b/src/mantle/support/helpers/helpers-general.php index ab095d28..0b0c190f 100644 --- a/src/mantle/support/helpers/helpers-general.php +++ b/src/mantle/support/helpers/helpers-general.php @@ -428,3 +428,51 @@ function hook_callable( string $hook, callable $callable, int $priority = 10 ): $callable(); } } + +/** + * Validates a file name and path against an allowed set of rules. + * + * A return value of `1` means the file path contains directory traversal. + * + * A return value of `3` means the file is not in the allowed files list. + * + * @see validate_file() in WordPress core. + * + * @param string $file File path. + * @param string[] $allowed_files Optional. Array of allowed files. Default empty array. + * @return int 0 means nothing is wrong, greater than 0 means something was wrong. + */ +function validate_file( $file, $allowed_files = [] ) { + // Proxy back to the core function if it exists, allowing Windows drive paths. + if ( function_exists( 'validate_file' ) ) { + $retval = \validate_file( $file, $allowed_files ); + return in_array( $retval, [ 0, 2 ], true ) ? 0 : $retval; + } + + if ( ! is_scalar( $file ) || '' === $file ) { + return 0; + } + + // `../` on its own is not allowed: + if ( '../' === $file ) { + return 1; + } + + // More than one occurrence of `../` is not allowed. + if ( preg_match_all( '#\.\./#', $file, $matches, PREG_SET_ORDER ) && ( count( $matches ) > 1 ) ) { + return 1; + } + + // `../` which does not occur at the end of the path is not allowed. + if ( str_contains( $file, '../' ) && '../' !== mb_substr( $file, -3, 3 ) ) { + return 1; + } + + // Files not in the allowed file list are not allowed. + if ( ! empty( $allowed_files ) && ! in_array( $file, $allowed_files, true ) ) { + return 3; + } + + // Absolute Windows drive paths ARE allowed. + return 0; +} diff --git a/src/mantle/testing/concerns/trait-interacts-with-cron.php b/src/mantle/testing/concerns/trait-interacts-with-cron.php index 314a4ddc..55cb555e 100644 --- a/src/mantle/testing/concerns/trait-interacts-with-cron.php +++ b/src/mantle/testing/concerns/trait-interacts-with-cron.php @@ -3,6 +3,7 @@ * Interacts_With_Cron trait file. * * @package Mantle + * * @phpcs:disable WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid */ diff --git a/src/mantle/view/engines/class-file-engine.php b/src/mantle/view/engines/class-file-engine.php index f161d6e4..aeff7d6e 100644 --- a/src/mantle/view/engines/class-file-engine.php +++ b/src/mantle/view/engines/class-file-engine.php @@ -9,6 +9,8 @@ use Mantle\Contracts\View\Engine; +use function Mantle\Support\Helpers\validate_file; + /** * File Engine to load raw view files. */ diff --git a/src/mantle/view/engines/class-php-engine.php b/src/mantle/view/engines/class-php-engine.php index ef9ca157..03695792 100644 --- a/src/mantle/view/engines/class-php-engine.php +++ b/src/mantle/view/engines/class-php-engine.php @@ -10,6 +10,8 @@ use Mantle\Contracts\View\Engine; use Throwable; +use function Mantle\Support\Helpers\validate_file; + /** * PHP Template to load WordPress template files. */