validate_file()WP 1.2.0

Checks the given string to see if it is a valid file path (file name). If the check passes, it returns 0; if not, it returns: 1, 2, or 3.

Used to prevent Directory traversal attacks.

1 time — 0.000018 sec (very fast) | 50000 times — 0.01 sec (speed of light) | PHP 7.1.2, WP 4.7.5

No Hooks.

Returns

Int.

  • 0 - check passed;
  • 1 - means that the file contains ../ (Go to the parent directory). What is passed to the command may allow reading/writing files in parent directories — which is unacceptable from a security standpoint;
  • 2 - means that $file contains : as the second character (Drive for Windows; absolute path). Unacceptable for the same reasons;
  • 3 - means that the file is not in the list of allowed files specified in the $allowed_files parameter.

Usage

validate_file( $file, $allowed_files );
$file(string) (required)
Path to the file.
$allowed_files(array)
List of allowed files that the variable $file must match.
Default: ''

Examples

0

#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)

Notes

Be careful when checking the returned result, as if the check passes, the function will return 0, and if it does not pass, it will return an integer. Therefore, you should check like this:

if( validate_file( $file ) === 0 )
	echo 'check passed';
else
	echo 'check not passed';

Changelog

Since 1.2.0 Introduced.

validate_file() code WP 6.9

function validate_file( $file, $allowed_files = array() ) {
	if ( ! is_scalar( $file ) || '' === $file ) {
		return 0;
	}

	// Normalize path for Windows servers.
	$file = wp_normalize_path( $file );
	// Normalize path for $allowed_files as well so it's an apples to apples comparison.
	$allowed_files = array_map( 'wp_normalize_path', $allowed_files );

	// `../` 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 not allowed:
	if ( ':' === substr( $file, 1, 1 ) ) {
		return 2;
	}

	return 0;
}