$input * @return array */ public function detect(Context $context, array $input = []): array { $name = (string)($input['name'] ?? ''); $origName = (string)($input['orig_name'] ?? $name); $suspicious = false; $reasons = []; if ($origName !== $name || strpos($origName, '/') !== false || strpos($origName, '\\') !== false) { $suspicious = true; $reasons[] = 'bad_name'; } if ($this->isSuspiciousFilename($name)) { $suspicious = true; $reasons[] = 'bad_name'; } return [ 'suspicious' => $suspicious, 'reasons' => $reasons, ]; } private function isSuspiciousFilename(string $name): bool { $n = strtolower($name); if (strpos($n, '../') !== false || strpos($n, '..\\') !== false || strpos($n, "\0") !== false) { return true; } if (preg_match('/\.(php|phtml|phar|php\d|pl|cgi|sh|asp|aspx|jsp)$/i', $n)) { return true; } if (preg_match('/\.(php|phtml|phar|php\d|pl|cgi|sh|asp|aspx|jsp)\./i', $n)) { return true; } if (preg_match('/^\.(php|phtml|phar|php\d)/i', $n)) { return true; } return false; } }