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. Узнаете до того, как обновите прод.

Подписаться

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

timeman 26.350.0 Заметное Свежее

Timeman 26.350.0: план дня пишется в нужную запись, блоки БП возвращают Saved

В timeman 26.350.0 для коробочного Битрикс24 блоки «Сохранить план на день» и «Сохранить отчёт сотрудника за день» из нового конструктора бизнес-процессов научились писать в заданную запись рабочего дня, оставлять Markdown как есть и сообщать, сохранилось ли (у отчёта новые настройки в конструкторе,…

2 мин
rpa 26.300.0 Безопасность Свежее

Rpa 26.300.0: права на перемещение элементов наконец проверяются

До RPA 26.300.0 `UserPermissions::canMoveItem()` сразу отвечал `true`, и любой сотрудник, кроме экстранет-пользователей, мог перетащить любой элемент на любую стадию, а права стадии на перемещение не учитывались. Теперь права проверяются, а тем, кто может только смотреть, `rpa.item.get` и `rpa.item….

3 мин
booking 26.500.100 Заметное Свежее

Booking 26.500.100: addList отвечает ошибкой, когда не создал ни одной брони, а четыре колонки дат стали DATETIME

В коробочный Битрикс24 пришёл booking 26.500.100 с двумя правками. AJAX-экшен `booking.api_v1.Booking.addList` теперь возвращает ошибку, если не создал ни одной брони. Апдейтер переводит четыре колонки дат с `TIMESTAMP` на `DATETIME`, и в `install/migrations/tables.php` они объявлены через `datetime…

3 мин
socialnetwork 26.200.0 Безопасность Свежее

Socialnetwork 26.200.0: XSS в заявках и списке участников, копирование проекта по праву редактирования и курсор в log.blogpost.get

Socialnetwork 26.200.0 закрывает XSS в списке участников проекта и в заявках в группы, подмену ссылок через название группы и утечку задач в контекст AI. Копировать проект теперь можно только с правом на редактирование. Администраторам, у которых стояли 26.100.0 или 26.150.0, стоит проверить права с…

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

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

на связи

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

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

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

Войти