# Понимание методов Pillow `open()`, `verify()`, `load()` с точки зрения безопасности Загрузка изображения — это не просто «получение файла», а **передача внешнего ввода в декодер (парсер)**. Поэтому важнее не то, что делают методы Pillow, а **когда они вызываются (т.е. когда открывается поверхность атаки)**. --- ## `open()` — это не «поднятие пикселей» {#sec-2e015f3fe462} `Image.open()` работает **лениво**. Он открывает файл и определяет его формат, но **пиксельные данные могут не считываться**. Файл может оставаться открытым. В безопасной и операционной практике `open()` используется так: * Сначала с помощью `open()` получаем лёгкую информацию: формат, ширину/высоту * На основе политики блокируем: разрешённые форматы, максимальное разрешение/число пикселей, лимит размера загрузки * Затем переходим к следующему этапу (проверка/декодирование) То есть `open()` безопасно использовать как инструмент для извлечения информации до декодирования. --- ## Что гарантирует `verify()` и что не гарантирует {#sec-bb315850bac9} `verify()` пытается убедиться, что файл не повреждён, но **не декодирует данные изображения**. Если обнаружены проблемы, генерируется исключение, и чтобы продолжить работу с изображением, его нужно открыть заново. Выводы с точки зрения безопасности: * **Плюс:** быстро отфильтровывает «повреждённые» файлы, не выполняя тяжёлого декодирования * **Минус:** прохождение `verify()` не означает полной безопасности; проблемы могут проявиться только при `load()` --- ## `load()` опасен, если вызывать его в процессе проверки {#sec-1eb3249bd446} `load()` действительно **декодирует (включая распаковку) и загружает пиксели в память**. Это сразу создаёт поверхность DoS-атаки, так как даже маленький файл может распаковаться в огромный объём данных. Pillow предупреждает о «весной декомпрессии» и имеет защиту по умолчанию (например, порог 128 Мп). Django, по той же причине, валидации изображений использует `verify()` вместо `load()`. В коде есть комментарий: «`load()` загружает всё изображение в память и может стать вектором DoS». --- ## При использовании Django/DRF: `ImageField` уже вызывает `verify()` — дублирование может быть избыточным {#sec-c03f143819d2} Валидация `ImageField` в Django использует `Image.open()` + `verify()`. Аналогично `serializers.ImageField` в DRF делегирует проверку Django. Если вы уже используете `serializers.ImageField`, то: * Вызов `verify()` в `validate()` обычно избыточен * Для более строгой бизнес‑валидации можно принимать файл через `FileField` и самостоятельно строить пайплайн проверки, что делает ответственность более прозрачной --- ## Как обеспечить «безопасность» загруженных файлов {#sec-bafb5e21c1fb} ![Диаграмма безопасной обработки загруженных файлов](/media/editor_temp/6/489648ac-eb83-4132-808b-f3ce0e07c366.png) Практичное решение: 1. **Не используйте оригинальный файл напрямую**. Декодируйте его на сервере и сохраняйте только результат. 2. С помощью `open()` считываем лёгкую информацию (формат, размеры) и применяем первичную фильтрацию. 3. `verify()` удаляет явно повреждённые файлы. 4. В ограниченной среде декодируем и нормализуем в стандартные пиксели (RGB/RGBA). 5. Перекодируем в выбранный сервером формат и сохраняем новый файл. 6. Сервис хранит и обслуживает только серверно перекодированный файл. Преимущество: сервер контролирует конечный формат, удаляя лишние метаданные и аномалии. Однако перекодирование всё равно включает `load()`, поэтому важно установить ограничения по количеству пикселей/памяти и выполнять это в изолированном процессе. --- ## Итоги {#sec-7d348ef3294d} * `open()` — «идентификация + сбор лёгкой информации» (пиксели могут отсутствовать) * `verify()` — «первичный фильтр повреждений» (без декодирования, при дальнейшей работе требуется повторное открытие) * `load()` — «начало декодирования/использования памяти» (не использовать в процессе проверки) * Практический подход к безопасной загрузке: **доверять только серверно перекодированным файлам** (с ограничениями и изоляцией) **Смотрите также**: - [Как выглядит файл изображения для разработчика? Разбираем структуру](/ko/whitedec/2026/1/14/developer-view-image-file-common-structure/) - [Гайд по безопасности загрузки изображений в Django: как не «провалить» сервер](/ko/whitedec/2026/1/13/django-image-upload-security-guide/) - [python-magic: лучший способ определить тип файла по содержимому, а не по расширению](/ko/whitedec/2026/1/15/python-magic-file-type-detection/)