removeDirectory - prevent accidental whipe of, for example, root dir

Is there a best practice preventing BaseFileHelper::removeDirectory() from recursive deleting directory / ? Or a ‘too high’ directory in the domain structure?
When having bad luck a script that pulls this off manages to whipe the complete domain directory from the filesystem (I had bad luck a few times this year).
Besides, it’s almost undoable tracking the culprit (files removed by php are ‘legit’ actions), but found it in the end!

Some ideas of mine:

write a wrapper, and check:

  • $dir is not equal to ‘/’, or
  • $dir is minimum x levels away from DOCUMENT_ROOT, or
  • $dir is in whitelist of deletable dirs

How did others solve this problem?

Yii2: baseFileHelper::removeDirectory
Yii1: CFileHelper::removeDirectory

You could wrap it into another helper that does necessary checks and throws an exception.


I’ve created a ‘whitelist’ of dirs that may be cleared from subdirs,
and wrapped created a removeDirectory() wrapper to solve it:


'params' => array(
	/* A whitelist that's used to prevent functions as:
	 *  - CFileHelper::removeDirectory()
	 * to completely whipe the domain folder, subdomain or just an important folder.
	 * The subdirectories of the following paths are considered 'save' for recursive removal
	 * Example: "/tmp" it's save to remove recursive "/tmp/test" (but not /tmp itself!)
	 * WARNING: Make sure you don't include a path like '/' or 'document root' ! ! !
	'directories_safe_to_empty' => array(

Snippet from my FileHelper using above whitelist:

class FileHelper extends CFileHelper
	 * Removes directory after confirming it's whitelisted as 'safe for recursive removal'.
	 * See whitelist in config['directories_safe_to_empty']
	public static function removeDirectory($directory, $options=array())
		$realPath = realpath($directory);
			Yii::log("Invalid path passed to removerecursive according to realpath: '$directory'", "warning", 'shared.components.FileHelper');
			// path doesnt exist so it doesnt have to be removed :)
			return true;

			return false;
		CFileHelper::removeDirectory($realPath, $options);
	 * Checks the passed dir against a whitelist of dirs that are safe for recursvie removal.
	 * The passed dir must be a subdir of one of the whitelisted dirs !
	 * @param string $dir the path of a dir to be checked
	 * returns boolean
	public static function isSafeForRecursiveRemoval($dir)
		$realPath = realpath($dir);
			return false;
		// Yii::app()->params['paths']
		$config = Yii::app()->params;
		if(!isset($config['directories_safe_to_empty']) || !is_array($config['directories_safe_to_empty'])){
			Yii::log("Config key params['directories_safe_to_empty'] not set or not an array", "error", 'shared.components.FileHelper');
			return false;
		$continueRemoval = false;
		foreach($config['directories_safe_to_empty'] as $idx => $safeParent){
			$realParent = realpath($safeParent);
				Yii::log("Invalid path according to realpath: params['directories_safe_to_empty'][\$idx] = '$safeParent'", "error", 'shared.components.FileHelper');
			// dir to be removed is in parent's path,
			// and path of dir to be removed is longer than parents
			if(strpos($realPath, $realParent.'/') === 0 && (strlen($realPath) > strlen($realParent.'/'))){
				return true;
		// echo 'path is not safe for recursive removal';
		Yii::log("Trying to recursive remove unsafe dir: '$realPath'", "warning", 'shared.components.FileHelper');
		// Yii::trace("Trying to recursive remove unsafe dir: '$realPath'", 'shared.components.FileHelper');
		return false;
1 Like