$pattern])); return; } } // 절대 경로 방지 (Windows와 Linux 모두 지원) if ( Str::startsWith($decodedPath, '/') || Str::startsWith($decodedPath, '\\') || preg_match('/^[a-zA-Z]:/', $decodedPath) // Windows 드라이브 문자 ) { $fail(__('validation.template_path.absolute_path_not_allowed')); return; } // NULL 바이트 공격 방지 if (Str::contains($decodedPath, "\0")) { $fail(__('validation.template_path.null_byte_detected')); return; } // 경로 정규화 $normalizedPath = str_replace(['\\', '/'], DIRECTORY_SEPARATOR, $decodedPath); // 실제 경로 검증 $fullPath = realpath($this->basePath . DIRECTORY_SEPARATOR . $normalizedPath); // realpath 실패 시 (파일이 존재하지 않을 수 있음) if ($fullPath === false) { // 경로 구성만 검증 (파일 존재 여부는 Controller에서 체크) $fullPath = $this->basePath . DIRECTORY_SEPARATOR . $normalizedPath; } // 기준 경로 외부 접근 방지 $realBasePath = realpath($this->basePath); if ($realBasePath === false || !Str::startsWith($fullPath, $realBasePath)) { $fail(__('validation.template_path.outside_base_directory')); return; } } }