validate_file()
Checks a file path (including relative) for forbidden constructs and for compliance with the list of allowed files.
It is used in the core when validating plugin paths, selecting templates, editing files, and unpacking archives.
It is used to prevent Directory traversal attacks.
A successful check does not confirm that the file exists or that the file has access permissions. The function does not check the file contents, extension, and MIME type.
Be careful: if the check passes, the function returns 0, and if it fails, it returns a number. Therefore, you should check like this:
if( validate_file( $file ) === 0 ) echo 'check passed'; else echo 'check did not pass';
Use validate_file_to_edit() when you need to check a path for editing with execution halted via wp_die() on error codes 1 and 3. For code 2, this wrapper returns null.
No Hooks.
Returns
int.
0- check passed.1- a forbidden construct containing../was detected.2- the second character of the normalized path equals:, for example inC:/file.php.3- the path is missing from a non-empty list of allowed files.
Error checks are performed in the order 1, 3, 2. If multiple violations occur, the result corresponds to the first check that triggered.
Usage
validate_file( $file, $allowed_files );
- $file(string) (required)
Path to the file.
Before checking, it is normalized via wp_normalize_path(): backslashes are replaced with forward slashes, repeated slashes are reduced except for the two initial ones, and the drive letter is converted to uppercase.
Code
1occurs if after normalization:- The path equals
../. - The substring
../occurs more than once. - The only substring
../is not at the end of the path.
Paths
folder/../,folder/..,..and absolute Unix paths like/etc/passwdare not rejected by themselves. An empty string and non-scalar values, such asnull, an array, or an object, immediately result in0, even if$allowed_filesis not empty. Check the type and non-empty value separately.- The path equals
- $allowed_files(array)
Allowed paths. Each element is normalized the same way as
$file. Then a strict comparison of the full path with the array elements is performed. File name casing is respected; patterns like*.phpare not supported.An empty array disables this check. The presence of a path in the list does not cancel the other checks.
Default:
[]
Examples
#1 Demo of file path checks
A path that will pass inspection:
$path = 'uploads/2012/12/my_image.jpg'; echo validate_file( $path ); // print 0 (valid path)
A path that will not pass inspection:
$path = '../../wp-content/uploads/2012/12/my_image.jpg'; echo validate_file( $path ); // print 1 (inaccessible path)
#2 Demonstration
echo validate_file( '' ); // 0 echo validate_file( null ); // 0 echo validate_file( false ); // 0 echo validate_file( 0 ); // 0 echo validate_file( [] ); // 0 echo validate_file( 'image.jpg' ); // 0 echo validate_file( 'uploads/image.jpg' ); // 0 echo validate_file( 'uploads//image.jpg' ); // 0 echo validate_file( '/etc/passwd' ); // 0 echo validate_file( '..' ); // 0 echo validate_file( 'uploads/..' ); // 0 echo validate_file( 'uploads/../' ); // 0 echo validate_file( '../' ); // 1 echo validate_file( '../image.jpg' ); // 1 echo validate_file( 'uploads/../x' ); // 1 echo validate_file( 'uploads/../../' ); // 1 echo validate_file( '..\\image.jpg' ); // 1 echo validate_file( 'C:/image.jpg' ); // 2 echo validate_file( 'C:\\image.jpg' ); // 2 echo validate_file( 'C: image.jpg' ); // 2 $allowed = [ 'uploads/image.jpg' ]; echo validate_file( 'uploads/image.jpg', $allowed ); // 0 echo validate_file( 'uploads\\image.jpg', $allowed ); // 0 echo validate_file( 'uploads//image.jpg', $allowed ); // 0 echo validate_file( 'uploads/IMAGE.jpg', $allowed ); // 3 echo validate_file( 'image.jpg', $allowed ); // 3 echo validate_file( '', $allowed ); // 0 echo validate_file( null, $allowed ); // 0 echo validate_file( 'image.jpg', [ '*.jpg' ] ); // 3 echo validate_file( '../image.jpg', $allowed ); // 1 echo validate_file( 'C:/image.jpg', $allowed ); // 3 echo validate_file( '../image.jpg', [ '../image.jpg' ] ); // 1 echo validate_file( 'C:/image.jpg', [ 'C:/image.jpg' ] ); // 2
Changelog
| Since 1.2.0 | Introduced. |