Landing 26.1100.0: закрыта цепочка уязвимостей, заодно ужесточены repo.register, savePicture и проверка ссылок предпросмотра
Обновление безопасности
Закрыта уязвимость или ослабленная проверка прав. Ставить в первую очередь.
landing 26.1100.0 (сборка от 06.08.2026) почти целиком про безопасность. Закрыты исполнение кода через манифест repo-блока и импорт архива сайта, инъекция в eval() через CODE страницы, SSRF через обработчик виджета, XSS в выводе ассетов, предсказуемый в облаке md5-хеш предпросмотра. В комментариях ядра прямо названы тикеты Mantis #252937, 253773 и 253734. Попутно изменилось поведение публичных API. Сильнее всего это заденет тех, кто регистрирует блоки через REST, зовёт Manager::savePicture() с путём на диске или раздаёт ссылки на предпросмотр неопубликованного сайта.
Дифф на 1029 файлов, +29899/−19034 строк. Около 380 записей приходится на lang-файлы, ещё 240 на пересобранные бандлы. Схема БД не менялась.
Проверьте приложения, которые регистрируют блоки через landing.repo.register
Метод Bitrix\Landing\PublicAction\Repo::register() раньше проверял меньше. Теперь правила такие:
Кто может вызывать. Появилась проверка checkRepositoryAccess(): писать в репозиторий может REST-приложение (есть $app['CODE']) или администратор (Rights::isAdmin()). Остальные получают ошибку ACCESS_DENIED. То же самое для unregister.
Чей блок найдётся. Фильтр поиска записи теперь всегда ['=XML_ID' => ..., '=APP_CODE' => $app['CODE'] ?? false]. Вызов без контекста приложения больше не найдёт и не перезапишет блок чужого приложения с тем же XML_ID. Если вы так обновляли блоки админским скриптом, теперь появится дубль, а существующая запись не обновится.
Что сохранится. Поля и манифест проходят через новый allow-list Security\RepoNormalizer::normalize():
- неизвестные ключи полей и манифеста отбрасываются молча, без ошибки;
- у путей в
assets.cssиassets.jsпроверяются расширение, схема (только http/https) и запрещённые символы.
assets.class и callbacks метод register вырезал и раньше: первый в onRegisterCheckManifest(), второй в onRegisterBefore(). Для REST новое только allow-list остальных ключей и проверка путей ассетов.
Приложение отправило манифест, REST ответил успехом, а блок ведёт себя иначе, потому что часть манифеста до базы не дошла. Ошибки вы не увидите, придётся сравнивать отправленное с сохранённым.
Виджеты отдельно. Подтип widgetvue в manifest.block.subtype добавлен в запрещённые для обычного register, рядом с widget. Такой вызов вернёт ошибку UNSUPPORTED_BLOCK_SUBTYPE (по коду 26.1100.0). Виджет регистрируется только через RepoWidget::register().
Наследникам. Удалён protected static Repo::onRegisterCheckManifest(array &$manifest). Переопределение этого хука в своём классе больше не вызывается, а обращение parent::onRegisterCheckManifest() закончится фаталом.
Блоки из репозитория больше не исполняют код из манифеста
Раньше Block::getAsset() превращал assets.class в путь для include php-файла, а Block::createFromRepository() вызывал callbacks.afteradd. REST-метод register эти ключи вырезал, но в b_landing_repo блок попадает и в обход него: через импорт архива сайта, прямой вызов Landing\Repo::add(), плюс там лежат старые записи. По комментарию в RepoNormalizer, любое из этих значений в базе означало исполнение произвольного кода на портале.
Теперь callbacks.afteradd вызывается только через новый Block::executeAfterAddCallback(). Для repo-блока колбэк сработает, только если это \Closure. В Block::getAsset() у repo-блока читаются лишь ключи css, js, ext. Тот же вызов подставлен в PublicAction\AiBlock.
Если ваш модуль клал afteradd или assets.class через Landing\Repo::add() или импорт, колбэк перестанет срабатывать, а php-файл из assets.class больше не подключится. Ошибок в логах не будет.
Импорт архива сайта тоже шёл мимо санитайзера: Transfer\Script\Action\Closet\BlockTrait клал repo_info в Repo::add() как есть. Теперь данные проходят через RepoNormalizer. Отклонённый контент при этом не выбрасывается, а сохраняется очищенным.
Repo::bind: без REST-приложения привязка не сработает
Repo::bind() теперь требует контекст REST-приложения и установленный модуль rest. Без них вернётся ACCESS_DENIED. Дополнительные проверки:
- код размещения обязан начинаться с
LANDING_, иначеPLACEMENT_UNKNOWN; - обработчик проверяется через
\Bitrix\Rest\HandlerHelper::checkCallback(), при неудачеPLACEMENT_HANDLER_INVALID; APP_IDберётся только из приложения, значение из входных полей игнорируется;- в
PlacementTableпишетсяUSER_ID = PlacementTable::DEFAULT_USER_ID_VALUE.
RepoWidget::register: обработчик виджета на локальном адресе больше не пройдёт
WIDGET_PARAMS.handler проверяется через Sanitizer::sanitizeWidgetHandlerUrl(). Принимается только абсолютный http(s)-URL. Хост не может быть приватным, loopback или зарезервированным IP, не может быть и «числовой» записью адреса. Протокол https обязателен для нового виджета и при смене обработчика, http остаётся только у неизменённого обработчика. Ошибка в REST-ответе — WIDGET_HANDLER_INVALID.
Больше всего это заденет dev-стенды. Виджет с обработчиком на http://192.168.x.x/... или http://127.0.0.1/... зарегистрировать не получится. Уже зарегистрированные виджеты с приватным адресом тоже перестанут работать, потому что Controller\Vibe проверяет адрес при каждом запросе к обработчику и отвечает ошибкой HANDLER_ADDRESS_NOT_ALLOWED.
Причина — SSRF. Controller\Vibe раньше делал (new HttpClient())->post($url, $params) по URL из манифеста без каких-либо проверок. В Sanitizer::isUnsafeAddressHost() отдельно отсекаются записи вида 127.1, 2130706433, 0177.0.0.1, 0x7f.0.0.1. Рядом комментарий: ctype в PHP облака не встроен, а pcre есть всегда, поэтому проверки написаны на регулярках.
Manager::savePicture с путём на диске теперь вернёт false
У Manager::savePicture() появился четвёртый параметр и изменилось поведение:
public static function savePicture($file, $ext = false, $params = array(), bool $trustedSource = false)
Без $trustedSource = true:
- локальный путь (
/upload/...) даётfalse; - файловый массив обязан пройти
is_uploaded_file(). Массив, собранный руками черезCFile::MakeFileArray(), не подойдёт: метод вернётfalseи запишет в журнал событийLANDING_FILE_UNTRUSTED_SOURCEс ключами массива.
Расширение сверяется со списком изображений при любом значении флага, но только для base64-массива [имя, данные].
Комментарий в ядре говорит, что ветка локального пути оставлена для обратной совместимости с вызовами вне монорепозитория. Но без флага она не работает. Фатала и исключения нет. Для локального пути метод тихо вернёт false, для массива оставит ещё и запись в журнале. Если результат у вас не проверялся, картинка у блока не появится.
Было и стало:
use Bitrix\Landing\Manager;
// До 26.1100.0 работало, теперь вернёт false
$picture = Manager::savePicture('/upload/import/hero.jpg');
// Путь сформирован вашим кодом, а не пришёл от пользователя
$picture = Manager::savePicture(
'/upload/import/hero.jpg',
false,
[],
trustedSource: true,
);
if ($picture === false)
{
$logger->warning('Landing: не удалось сохранить картинку', ['path' => '/upload/import/hero.jpg']);
}
Ставьте trustedSource: true только там, где путь целиком формирует ваш код. Если в путь попадает что-то из запроса, с этим флагом вы заново откроете закрытую уязвимость.
Все выданные ссылки предпросмотра умрут
Site::getPublicHash() раньше считал md5() в облаке от хоста и пути публикации, в коробке от домена, ID сайта и лицензионного ключа. Облачный хеш можно было предсказать. Теперь это подпись Bitrix\Main\Security\Sign\Signer с солью landing_public_hash. Сравнение идёт через новый Site::isPublicHashValid() на hash_equals, он же подставлен в компонент landing.pub.
Все ранее выданные ссылки на предпросмотр неопубликованного сайта после обновления перестанут открываться. Заказчикам, которым вы отправляли такие ссылки на согласование, придётся разослать новые. В своём коде, где хеш сравнивался вручную, переходите на штатную проверку:
use Bitrix\Landing\Site;
$hash = (string)$request->get('hash');
if (!Site::isPublicHashValid($siteId, $hash))
{
return null;
}
CODE страницы, сайта и папки: часть символов под запретом
В onBefore*-проверки LandingTable, SiteTable и FolderTable добавлен Security\SyspageUrl::isSafeCode(). Запрещены символы ' " ` $ \ < > ( ) { } и управляющие байты. При нарушении add()/update() вернёт неуспешный результат с кодом WRONG_CODE_CHARS.
URL системных страниц #system_* подставляются в контент блока, а контент исполняется через eval() в Block::view(). Это тикет Mantis #253773, инъекция через CODE.
Тексты ошибок захардкожены по-английски, без Loc, и пользователь русского портала увидит английскую фразу. Импортёры, которые генерируют CODE из заголовков, лучше прогонять через ту же проверку заранее:
use Bitrix\Landing\Security\SyspageUrl;
use Bitrix\Main\Error;
use Bitrix\Main\Result;
$result = new Result();
if (!SyspageUrl::isSafeCode($code))
{
$result->addError(new Error('Недопустимые символы в коде страницы', 'WRONG_CODE_CHARS'));
return $result;
}
Site::updateFolder и перенос папок между сайтами
Site::updateFolder() получил новые проверки:
- папка и
PARENT_IDдолжны принадлежать сайту; - вложить папку в саму себя или в своего потомка нельзя (
MOVE_RESTRICTION); INDEX_IDдолжен быть страницей этого же сайта (FOLDER_INDEX_OUT_OF_SITE).
Кроме того, FolderTable при смене SITE_ID у существующей папки требует право delete на старом сайте и edit на новом. Скрипты, переносившие папки обычным update с новым SITE_ID, начнут получать отказы.
Шлюз PublicAction: лимит batch и общая фраза вместо текста исключения
В PublicAction, через который идут AJAX и REST, изменились три вещи.
- В AJAX-batch редактора (
PublicAction::ajaxProcessing()) можно передать не больше 500 команд (MAX_BATCH_ITEMS), дальше ошибкаBATCH_LIMIT_EXCEEDED. Загрузка файлов внутри такого batch запрещена:BATCH_FILES_NOT_ALLOWED. По 100 команд режет только новыйBX.Landing.Backend.batchList()(BATCH_ITEMS_PER_REQUEST), и вызывает его пока лишьgetLandings(). Обычныйbatch()ничего не режет, так что свой вызовbatch()на 500+ команд получитBATCH_LIMIT_EXCEEDED. REST-вызовы черезrestGateway()эту проверку не проходят. - Scope команды больше не наследуется от соседней команды в batch. Если у команды
scopeне указан, вызываетсяType::clearScope(). В AJAX-шлюзе командам без своегоscopeподставляется общийtypeзапроса (getBaselineScope()). Кто рассчитывал, что первая команда «включит» scope для остальных, должен указывать его в каждой команде (в AJAX хватит общегоtype). - Текст исключения действия отдаётся клиенту только при включённом
exception_handling.debug. Иначе приходит общая фраза, а детали пишутся в журнал событий с типомLANDING_ACTION_EXCEPTIONи троттлингом 600 секунд. При отладке интеграции сообщение об ошибке теперь надо искать в журнале событий, в ответе его не будет.
Method-static кеши прав в Rights::hasAccessForSite/hasAccessForLanding, Role, LandingTable, SiteTable «протекали» между командами batch. Scope переключается покомандно внутри одного PHP-процесса, и первая команда фиксировала роли для всех следующих. Кеши переведены на ключ по scope или убраны. Агенты в lib/agent.php теперь сохраняют и восстанавливают scope и глобальный флаг прав вызывающего.
Остальные ломающие изменения
PublicAction\Domain::check()— клиентский$filterурезан до ключейID,=ID,!ID,!=IDс целочисленными значениями. В комментарии объяснение: через dot-нотацию ORM получался оракул по чужим таблицам. Остальные ключи фильтра игнорируются.Site\Type::getScopeClass()— класс scope берётся из закрытого спискаSCOPE_CLASSES(GROUP, KNOWLEDGE, VIBE), а не склейкой пользовательского ввода с namespace. ПриватныйgetFullScopeClass()удалён. Свой класс, подложенный вBitrix\Landing\Site\Scope\*, больше не подхватится.Controller\Landing— переопределениеconfigureActions()убрано, метод теперь наследуется отMain\Engine\Controller. СgetByIdActionснят префильтрActionFilter\Extranet, потому что базы знаний групп открыты экстранет-пользователям.Controller\Tailwind, наоборот, теперь берёт...parent::getDefaultPreFilters()и требует POST дляsaveCss. БазовыйControllerвключаетAuthentication,HttpMethodиCsrf(по коду 26.1100.0), так что кsaveCssперестанут проходить и GET-запросы, и запросы безsessid.Node\StyleImg::getNode(Block $block, $selector, ?array $preloadedFiles = null)— добавлен необязательный параметр. Заденет только наследников с переопределённым методом: получат фатал о несовместимой сигнатуре.- Copilot — в интерфейс
Copilot\Generation\Scenario\IScenarioдобавленыisAnalyticStartEnabled()иonGenerationError(Generation, GenerationException). Фатал о нереализованных абстрактных методах получат только классы, которые реализуютIScenarioнапрямую. У наследниковBaseScenarioдля обоих методов есть реализации по умолчанию. УдаленыIntegration\AiAssistant\WidgetBotResolverиWidgetDataProvider::getAiAssistantBotId(). - Роли в scope —
PublicAction\RoleпроверяетcheckScope($id): роль чужого scope нельзя ни прочитать, ни изменить. Переключение режима прав доступно только приRights::canSwitchMode()(вне scope или админу). Rights::ADDITIONAL_RIGHTS— ключmainpage_createзаменён наvibe_create,vibe_admin,vibe_menu24. Первые два без явной настройки запрещены (DENIED_WHEN_UNCONFIGURED). Код, который читаетRights::ADDITIONAL_RIGHTS['mainpage_create'], получит предупреждение Undefined array key иnullвместо кода права.- Удалён шаблон
.defaultкомпонентаlanding.site_copilot(остался толькоai) и JS-расширениеlanding.animation.copilotцеликом. Если вы копировали шаблон.defaultк себе или подключали это расширение, проверьте.
Deprecated
Новых @deprecated в релизе нет. Всё удалённое удалено сразу, без переходного периода.
Новое: namespace Security и пачка санитайзеров
RepoNormalizer — тот же allow-list, что применяет ядро
Bitrix\Landing\Security\RepoNormalizer::normalize() — единая нормализация блока репозитория для REST и импорта. Возвращает DTO NormalizedRepoBlock с двумя публичными свойствами: fields и contentRejected. Через него можно заранее проверить, что ядро сделает с вашими полями и манифестом. Манифест лежит в fields['MANIFEST'] уже сериализованным, в том виде, в каком попадёт в b_landing_repo, поэтому для сравнения его придётся развернуть:
use Bitrix\Landing\Security\RepoNormalizer;
$normalized = RepoNormalizer::normalize(
fields: $fields,
manifest: $manifest,
xmlId: 'acme.hero_banner',
appCode: 'acme.landing_blocks',
);
$storedManifest = unserialize($normalized->fields['MANIFEST'], ['allowed_classes' => false]);
if ($normalized->contentRejected)
{
// register вернёт CONTENT_IS_BAD/PRESET_CONTENT_IS_BAD и ничего не сохранит
$logger->error('Контент repo-блока не прошёл санитайзер', ['xmlId' => 'acme.hero_banner']);
return;
}
$dropped = array_filter([
'fields' => array_keys(array_diff_key($fields, $normalized->fields)),
'manifest' => array_keys(array_diff_key($manifest, $storedManifest)),
'manifest.block' => array_keys(array_diff_key($manifest['block'] ?? [], $storedManifest['block'] ?? [])),
]);
$assetsChanged = ($manifest['assets'] ?? []) != ($storedManifest['assets'] ?? []);
if ($dropped !== [] || $assetsChanged)
{
$logger->notice('Repo-блок будет сохранён не целиком', [
'dropped' => $dropped,
'assetsChanged' => $assetsChanged,
]);
}
Флаг contentRejected по-разному влияет на два входа. REST register при нём ничего не сохраняет и возвращает CONTENT_IS_BAD или PRESET_CONTENT_IS_BAD, а импорт сохраняет очищенный контент.
Sanitizer: проверка URL обработчика и CSS-ссылок
В Bitrix\Landing\Sanitizer появились sanitizeWidgetHandlerUrl(string $url, bool $requireHttps = false) и sanitizeCssUrl(string $url). hasDisallowedScheme() стал public static. Ещё добавлено восстановление тега <style>, разрезанного аудитором.
use Bitrix\Landing\Sanitizer;
use Bitrix\Main\Error;
use Bitrix\Main\Result;
$result = new Result();
$handlerUrl = Sanitizer::sanitizeWidgetHandlerUrl($handler, requireHttps: true);
if ($handlerUrl === '')
{
$result->addError(new Error('Обработчик виджета должен быть публичным https-адресом', 'WIDGET_HANDLER_INVALID'));
return $result;
}
Этим можно проверить обработчик у себя до отправки в RepoWidget::register(), чтобы не ловить WIDGET_HANDLER_INVALID на стороне портала.
Что ещё появилось
Security\SyspageUrl::isSafeCode()/sanitize()— защита URL системных страниц#system_*.AI\SiteBuilder\Html\AiBlockHtmlSanitizer::sanitize(string $html)— allow-list-санитайзер разметки AI-блоков наBitrix\Main\Web\DOMс пересериализацией дерева.- Хуки страниц —
Hook\Page\CssBlock::escapeCssForStyleTag()экранирует</styleкак\3c /style. ДобавленыHook\Page\ThemeFonts::sanitizeFontName()иHook\Page\Cookies::sanitizeColor(). Controller\Vibe::requestWidgetHandler()/createHandlerHttpClient()— запрос к обработчику виджета вынесен в отдельный метод: проверка URL, таймаут 5 секунд, лимит тела 1 МБ, отдельная обработка кодовPRIVATE_IP,URI_SCHEME,URI_HOST,URI_PUNICODE.authбольше не подмешивается в исходные$params.- Права —
Rights::canSwitchMode(),isGlobalOn(),isRightInScope(),hasCodeInScope(),isExtendedGrantAcceptable(),reset*Cache().Role::clearCache(),clearRolesCache(),isInCurrentScope().RoleTable::onAfterAdd/onAfterUpdateсбрасывают кеши. ПлюсSite\Type::isScopeEntered()иSite\Scope\Vibe::getOperationsForSite(). - Vibe —
Vibe\Vibe::canCreate()иAbstractVibeProvider::canCreate()/hasExplicitVibeRight(): создание главной страницы по явно выданному праву плюс проверка тарифной фичи. - Copilot: правка выбранного элемента AI-сайта — сценарий
ChangeAiSiteSelectedElementбыл ещё в 26.1000.0, теперь в его карте шагов появилисьTaskResolveChangeAiSiteSelectedElementиRequestChangeAiSiteSelectedElementBlockHtml. На фронте — TypeScript-расширениеlanding.copilot.element-picker. Фича спрятана за опциейlanding_ai_site_selected_element_enabled, по умолчаниюN. - Copilot, остальное — шаг
TaskFinishCreateAiSiteзавершает сценарийCreateAiSite. ХелперChangeAiSiteStructuralDiffловит структурную регрессию HTML вRequestImproveChangeAiSiteBlockHtml.GenerationErrorStatusMapperпереводит ошибку генерации в статус аналитики, его вызываютGenerationи сценарийChangeAiSite.AdditiveNodeTaggerвTaskPrepareChangeAiSiteBlocksMarkupвосстанавливает кодыai-node-*, которые модель потеряла при переписывании блока. - Метрика —
Metrika\BlockContentChangeDetector,BlockEditMetrikaSender(sendManualEdit/sendAiEdit),BlockContentKinds,EditorOpenEventResolver,PublicationErrorStatusMapper,SiteTypeResolver, а такжеLanding::getSiteTypeCode(). Это аналитика ручных и AI-правок блоков изPublicAction\Block. - По мелочи:
Agent::isFolderStorageAvailable(),Copilot\Generation::existsBySiteId()/isFinishedPersisted(),PublicAction::getBaselineScope()/writeExceptionToLog().
БД
Схема не менялась. Новый степпер Bitrix\Landing\Update\Repo\ContentSanitizer в два этапа по 200 строк вычищает уже сохранённые манифесты и контент: сначала b_landing_repo, затем экземпляры repo_% в b_landing_block. Переписываются только реально изменившиеся строки.
В самом диффе привязки степпера нет, класс только объявлен. По диффу не видно, запускается ли он автоматически при установке обновления. Поэтому не рассчитывайте, что старые записи в репозитории уже очищены.
Мелочи и находки
- XSS в выводе ассетов.
Assets\Managerподставлял путь ассета в<link href>и<script src>без экранирования, теперь тамhtmlspecialcharsbx($path, ENT_QUOTES). В шаблонах компонентов экранирование добавляли массово. В диффе 204 добавленные строки сhtmlspecialcharsbx|CUtil::JSEscape|Json::encodeпротив 43 удалённых. Например,CUtil::JSEscapeполучилTPL_CODEв шаблоне.defaultкомпонентаlanding.mainpage.pub, а вcomponent_epilog.phpуlanding.pubтеперь экранируются превью страницы, metaBitrix24SiteTypeи путь к favicon. - Промпт модерации лежит в модуле. В
lib/AI/SiteBuilder/Prompt/ai-moderate-topic.mdположен текст промпта модерации тематики AI-сайта (кодlanding_ai_site_moderation). В пометке сказано, что в рантайме он читается изb_ai_prompt, а файл служит «source of truth» и фикстурой дляModerationPromptContractTest. Внутри осталась внутренняя инструкция деплоя: загрузить тело шаблона на каждый целевой портал. - Аналитика шагов Copilot. У девяти шагов
Copilot\Generation\Step\*убраны переопределенияgetAnalyticEvent(), для них метод теперь возвращает null изBaseStep. Вызов не упадёт, сам метод объявлен вStep\Base\IStep. - Многооконный редактор и
instanceof Blob. File из другого окна не проходилinstanceof Blob. Вimagecompressorпоявилисьis-blob.js, который узнаёт Blob и File любого окна поObject.prototype.toString, иto-current-window-blob.jsсclone-blob.js, которые пересобирают такой объект конструкторами текущего окна. Вimageuploaderдобавленclone-file.js: он делает отдельную копию файла для каждого запрошенного размера, потому что имя для загрузки задаётся на самом объекте и общий файл переименовывался бы по разу на каждый размер.
Что делать
- Обновляйтесь не откладывая и сразу до 26.1100.200. Закрытые дыры серьёзные, а их механика теперь описана прямо в комментариях ядра. В самом 26.1100.0
Controller\DiskFileвсё ещё вызываетBlock::isContains(), удалённый в 26.1000.0, поэтому скачивание и просмотр файлов Диска из блоков не работают (по коду 26.1100.0). В 26.1100.200 это исправлено, подробности в разборе 26.1100.200. - Сделайте grep по своему коду:
savePicture(— где передаётся путь на диске или массив не из$_FILES, добавьтеtrustedSource: trueи проверку результата наfalse;getPublicHash— ручное сравнение хеша замените наSite::isPublicHashValid();onRegisterCheckManifest,WidgetBotResolver,getAiAssistantBotId— этих символов больше нет;mainpage_create— ключа вRights::ADDITIONAL_RIGHTSбольше нет, права теперьvibe_create,vibe_admin,vibe_menu24;implements IScenario— допишите два новых метода;landing.animation.copilotи шаблон.defaultуlanding.site_copilot— удалены.
- Если у вас REST-приложение с блоками, прогоните манифесты через
RepoNormalizer::normalize()на тестовом портале и посмотрите, что отбрасывается. Для блоков, которые попадают в репозиторий черезLanding\Repo::add()или импорт, наassets.classиcallbacksбольше не рассчитывайте. Виджеты регистрируйте черезRepoWidget::register(), обработчик должен быть на публичном https-адресе. - Placement'ы привязывайте только из контекста приложения, код размещения начинайте с
LANDING_. - Перевыпустите ссылки предпросмотра неопубликованных сайтов, которые уже отправили заказчикам.
- В импортёрах страниц проверяйте CODE через
SyspageUrl::isSafeCode()до сохранения и обрабатывайтеWRONG_CODE_CHARS. - В AJAX-batch редактора держите не больше 500 команд и не отправляйте в нём файлы.
scopeуказывайте в каждой команде, где он нужен (в AJAX хватит общегоtype). - Когда интеграция отвечает общей фразой вместо внятной ошибки, ищите детали в журнале событий по типу
LANDING_ACTION_EXCEPTION.
Устаревшие и удалённые API в этой версии
| Символ | Статус | Чем заменять |
|---|---|---|
Bitrix\Landing\PublicAction\Repo::onRegisterCheckManifest()
|
Удалено |
Bitrix\Landing\Security\RepoNormalizer::normalize()
|
Bitrix\Landing\Rights::ADDITIONAL_RIGHTS['mainpage_create']
|
Удалено |
Bitrix\Landing\Rights::ADDITIONAL_RIGHTS['vibe_create']
|
Bitrix\Landing\Integration\AiAssistant\WidgetBotResolver
|
Удалено | — |
Bitrix\Landing\Integration\AiAssistant\WidgetDataProvider::getAiAssistantBotId()
|
Удалено | — |