iblock · Информационные блоки 26.0.100 Безопасность

Iblock 26.0.100: ORM-поле USER_TYPE_SETTINGS_LIST больше не восстанавливает объекты

2 мин чтения
Узнавайте о ломающих изменениях Битрикса раньше, чем они доедут до прода: свежие разборы — в канале @bxmax_updates

Обновление безопасности

Закрыта уязвимость или ослабленная проверка прав. Ставить в первую очередь.

Сборка от 10 сентября 2026, содержательная правка в ней одна. Bitrix\Iblock\PropertyTable теперь десериализует поле USER_TYPE_SETTINGS_LIST (колонка USER_TYPE_SETTINGS) с запретом классов. Если вы пишете свои пользовательские типы свойств инфоблока и храните в настройках обычные массивы, для вас ничего не изменится. Если хранили там объект, ORM теперь вернёт __PHP_Incomplete_Class. Миграций БД нет, deprecated нет, публичные сигнатуры не менялись.

Проверьте, что лежит в USER_TYPE_SETTINGS

Поле USER_TYPE_SETTINGS_LIST (колонка USER_TYPE_SETTINGS в b_iblock_property) раньше было штатным ArrayField, а тот в decodePhp() зовёт unserialize($value) без ограничений. Теперь поле описано анонимным наследником ArrayField прямо в getMap(), и декодер у него свой:

        return unserialize($value, ['allowed_classes' => false]);

    

Правка касается чтения USER_TYPE_SETTINGS_LIST: явного select, select * и fetchObject(). Сериализованный объект в этом поле больше не восстановится, вместо экземпляра своего класса вы получите __PHP_Incomplete_Class. Отдельное поле USER_TYPE_SETTINGS (TextField на ту же колонку) ORM не десериализует и отдаёт строкой, как раньше. Там, где старое API само разбирает колонку (CIBlockPropertyResult, CIBlockElement), unserialize и до релиза вызывался с allowed_classes => false, так что объект приходил как __PHP_Incomplete_Class (по коду iblock 26.0.0 в эталоне).

Пользовательский тип заметит изменение там, где ядро копирует USER_TYPE_SETTINGS_LIST в USER_TYPE_SETTINGS перед вызовом типа. По коду в эталоне это, например, списки элементов в админке (iblock_element_admin.php:359, iblock_list_admin.php:343), грид (usertypepropertyfieldassembler.php:43) и фильтр элементов (elementfilterfields.php:495).

Допустим, кто-то решил, что хранить настройки типа в виде DTO удобнее, чем массивом:

        <?php declare(strict_types=1);

namespace Vendor\Catalog\Property;

final class RatingSettings
{
    public function __construct(
        public readonly int $maxStars = 5,
        public readonly bool $allowHalf = false,
    ) {}
}

// и в настройки свойства уехал объект:
// USER_TYPE_SETTINGS = serialize(['config' => new RatingSettings(10, true)])

    

После обновления чтение выглядит так:

        <?php declare(strict_types=1);

use Bitrix\Main\Loader;
use Bitrix\Iblock\PropertyTable;

Loader::requireModule('iblock');

$property = PropertyTable::query()
    ->setSelect(['ID', 'CODE', 'USER_TYPE_SETTINGS_LIST'])
    ->where('CODE', 'RATING')
    ->fetch();

$config = $property['USER_TYPE_SETTINGS_LIST']['config'];

var_dump($config instanceof \Vendor\Catalog\Property\RatingSettings); // false
var_dump($config::class); // __PHP_Incomplete_Class

$config->maxStars; // до свойств неполного объекта не достучаться

    

На стороне БД ничего не поменялось, в колонке лежит та же строка.

Храните настройки массивом скаляров

Обычные настройки пользовательских типов, то есть массивы со строками, числами и флагами, читаются как раньше. Если объект в коде всё-таки нужен, собирайте его из массива уже после чтения:

        <?php declare(strict_types=1);

use Vendor\Catalog\Property\RatingSettings;

// в USER_TYPE_SETTINGS лежит только это:
$settings = [
    'MAX_STARS' => 10,
    'ALLOW_HALF' => 'Y',
];

// $property получен из PropertyTable, как в примере выше,
// а DTO собираем сами, на своей стороне:
$stored = $property['USER_TYPE_SETTINGS_LIST'] ?? [];

$config = new RatingSettings(
    maxStars: (int)($stored['MAX_STARS'] ?? 5),
    allowHalf: ($stored['ALLOW_HALF'] ?? 'N') === 'Y',
);

    

Так настройки не зависят от того, существует ли класс, переименовали ли его и как именно ядро вызывает unserialize.

Мелочи и находки

  • Мотив в диффе не назван, комментария в коде нет. По самой правке (allowed_classes => false) это похоже на харднинг против PHP Object Injection через содержимое b_iblock_property.USER_TYPE_SETTINGS.
  • ArrayField в main не трогали, новой опции конфигурации у поля не появилось. ->configureSerializationPhp() остался на месте, переопределён только декодер. Других ArrayField с PHP-сериализацией в этом диффе нет.
  • Метода PropertyTable::decodePhp() из паспорта API не существует. Генератор приписал PropertyTable метод анонимного класса поля из getMap(), нового публичного API в релизе нет.
  • В остальном только версия: 26.0.0 → 26.0.100 в install/version.php, заодно убрали пустую строку после <?php и висячую запятую в массиве.

Что делать

  • Поищите в своих пользовательских типах свойств места, где в USER_TYPE_SETTINGS попадает что-то кроме массивов и скаляров.
  • Если нашли объект, пересохраните такие свойства с массивом скаляров, а DTO собирайте в коде после чтения.
  • Если в настройках у вас и так одни массивы, для вашего кода поведение прежнее.

Новая версия вышла — разбор уже в Telegram

В канале @bxmax_updates публикуем каждый свежий разбор: что сломается, что устарело и что появилось в API. Узнаете до того, как обновите прод.

Подписаться

Читайте дальше

iblock 26.100.0 Безопасность Свежее

Iblock 26.100.0: файловые поля в БП только по ID, REST v3 для элементов

Iblock 26.100.0 (сборка от 14 сентября 2026) закрывает две дыры: подстановку путей, URL и массивов файлов в файловые поля через документ бизнес-процесса и обход прав при inline-редактировании цен в админке. Первая правка сломает шаблоны БП и свои активити, которые пишут в поле «Файл» ссылку или путь…

5 мин
voximplant 26.900.0 Заметное Свежее

Voximplant 26.900.0: подписанные параметры экспорта статистики

Voximplant 26.900.0 подписывает имя компонента при экспорте детализации статистики. Обновление также исправляет REST-сценарии, отметку пропущенного переадресованного звонка и чтение настроек прокси.

1 мин
superset 26.700.0 Заметное Свежее

Superset 26.700.0: пользовательский контекст и проверяемый act-as

Версия 26.700.0 добавляет пользовательский контекст Superset в публичные провайдеры и команды. Проверяемый act-as для SQL Lab включается явно, поэтому существующие вызовы продолжают работать по-прежнему. Все новые параметры необязательны, прежние значения по умолчанию сохранены.

2 мин
sign 26.1200.0 Ломающее Свежее

Sign 26.1200.0: автоопределение бланков и удаление CRM API

Sign 26.1200.0 упрощает загрузку документов КЭДО, добавляет списки сотрудников в робот и обновляет «Мой сейф» без перезагрузки страницы. Перед обновлением проверьте интеграции с CRM и сервисом бланков: четыре публичные точки API удалены, а `CRM::saveCompanyStamp()` сменил тип результата.

4 мин
Мы используем файлы cookie для улучшения работы сайта. Продолжая использовать сайт, вы соглашаетесь с нашей политикой конфиденциальности.
AI Домовой

AI Домовой История

на связи

пишет…

Можно закрыть чат и перейти на другую страницу. Когда ответ будет готов, на кнопке Домового появится отметка.

Нет истории чатов
AI Домовой

Нужна авторизация

Войдите, чтобы задавать вопросы AI Домовому.

Войти