bizproc · Бизнес-процессы 26.1700.0 Безопасность

bizproc 26.1500.0–26.1700.0: закрыты дыры в правах, lib/ на PSR-4, задания выполняются пачкой

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

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

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

В БУС пришли три версии bizproc: 26.1500.0, 26.1600.0 и 26.1700.0. Каждая закрывает дыры в правах, последняя ещё и доступ к чужим файлам через задания, так что обновляйтесь. После обновления проверьте код, который подключает файлы модуля по путям, интеграции, которые передают в задания ID файлов, и доступ сотрудников к процессам инфоблоков. И решите, оставлять ли новый дизайнер, он теперь включён по умолчанию. Прошлый разбор модуля — bizproc 26.1450.0.

Новое

Выполняйте задания пачкой (26.1600.0)

Ajax-действие bizproc.task.doCollection применяет одно решение к нескольким заданиям. Оно принимает только POST и до 50 заданий за вызов. Задания выполняются по очереди без общей транзакции, по каждому приходит статус done, not_found, access_denied или error. На нём построено групповое действие «Выполнить задания» в bizproc.user.processes.

С 26.1700.0 значение файлового поля пачкой не передать. Задание, чьё файловое поле есть в общем запросе, получает ошибку TASK_FILE_FIELD_NOT_SHARED, остальные выполняются как обычно.

        // taskRequest повторяет то, что отправляет кнопка задания.
// У «Утверждения документа» кнопки называются approve и nonapprove.
async function approveTasks(taskIds, comment)
{
	const response = await BX.ajax.runAction('bizproc.task.doCollection', {
		data: {
			taskIds,
			taskRequest: { approve: 'Y', fields: { task_comment: comment } },
		},
	});

	const { results, doneCount } = response.data;
	results
		.filter((item) => item.status !== 'done')
		.forEach((item) => console.warn(item.taskId, item.status, item.errors));

	return doneCount;
}

approveTasks([101, 102, 103], 'Согласовано пачкой')
	.then((doneCount) => console.log(`Выполнено: ${doneCount}`))
	.catch((response) => console.error(response.errors)); // например, больше 50 заданий

    

Ходите во внешние API из процесса (26.1700.0)

Нода «Исходящий вебхук с ответом» (CBPOutgoingWebHookActivity) отправляет GET, POST, PUT, PATCH или DELETE и отдаёт следующим нодам ResponseBody, ResponseCode, ResponseHeaders, IsTransportError и ErrorMessage. Таймаут до 30 секунд, ответ до 1 МБ, редирект считается ошибкой. В каталоге нода появится после bizproc:outgoing_webhook_node_available=Y.

Запросы нода шлёт через Bitrix\Bizproc\Activity\Http\PublicAddressHttpClient, наследника Main\Web\HttpClient с защитой от SSRF. Он пускает только на публичные IPv4, отклоняет IPv6 и 100.64.0.0/10, а setPrivateIp() у него всегда ставит false. Дополнительные запрещённые диапазоны берутся из опции bizproc:outgoing_request_denied_ranges. Клиент пригодится своему действию или роботу, которому URL задаёт пользователь:

        <?php declare(strict_types=1);

use Bitrix\Bizproc\Activity\Http\PublicAddressHttpClient;
use Bitrix\Main\Loader;

Loader::requireModule('bizproc');

function fetchExternalJson(string $url): ?array
{
    $client = (new PublicAddressHttpClient(['redirect' => false, 'socketTimeout' => 5, 'streamTimeout' => 10]))
        ->setDeadline(15)
        ->setHeadersLengthMax(64 * 1024);

    $body = $client->get($url);
    if ($body === false) {
        // PRIVATE_IP, DENIED_IP или обычная сетевая ошибка
        AddMessage2Log(implode('; ', $client->getError()), 'bizproc');

        return null;
    }

    $data = json_decode($body, true);

    return is_array($data) ? $data : null;
}

    

Работайте над шаблоном вместе

Журнал изменений шаблона (26.1500.0) записывает, кто правил схему (человек, ИИ или система) и откуда пришла правка: из редактора, от Марты, от внешнего агента или от системы. Ленту отдаёт WorkflowTemplateHistoryService::getChangeEvents() с проверкой доступа. Записи хранятся 90 дней.

В 26.1600.0 появились заметки на схеме с упоминаниями через @ и блокировка редактирования шаблона на 10 минут (WorkflowTemplateLockService). С флагом useEditConflictGuard черновик сохраняется с проверкой ревизии, и если его успел изменить кто-то другой, сервис ответит DRAFT_REVISION_CONFLICT. Заметки и блокировка включаются опциями template_notes_available и template_edit_lock_available модуля bizprocdesigner, по умолчанию обе N.

В 26.1700.0 за опцией process_data_enabled появились «Данные процесса»: в шаблоне, созданном при включённой опции, стартовые параметры копируются в одноимённые переменные.

Триггер и API для своих действий

  • Триггер «Сотрудник уволен» (EmployeeDismissalTrigger, 26.1500.0) срабатывает по событию intranet:onAfterUserFire и передаёт в процесс userId, firedAt, name и lastName.
  • BaseType\ValueRule (26.1500.0): ограничения Min, Max и MaxLength в настройках поля под ключом ValueRule. Целые и строки проверяют по ним значение из формы.
  • CBPTrackingService::writeForced() (26.1700.0) пишет в журнал процесса в обход пропускаемых типов и без обрезки по размеру.
  • BaseType\Date::internalizeValue() (26.1700.0) принимает ['value' => '…', 'tz' => 'Europe/Moscow'], без tz берёт пояс текущего пользователя.
  • CBPActivity (26.1500.0) получил точки расширения для внешних ИИ-агентов: getAiPassthroughSettingNames(), getAiRestrictedSettingNames() и getAiEnforcedSettingValues() решают, что агент переносит как есть, что только копирует из опубликованного шаблона и что выставляет сам.

Что сломается

Проверьте пути и регистр классов (26.1500.0)

Каталог lib/ перевели на PSR-4: 260 файлов переименованы в CamelCase, например lib/basetype/inttype.php стал lib/BaseType/IntType.php. Классы и namespace прежние. Упадёт require по старому пути, а на регистрозависимой ФС ещё и обращение к классу с неверным регистром вроде Bitrix\Bizproc\Basetype\Inttype: файла в нижнем регистре, который загрузчик искал вторым, больше нет. Старые ajax-действия вида bizproc.task.do работают через карту контроллеров в autoload.php. Пути в своём коде найдёт grep:

        grep -rn "modules/bizproc/lib/" local/ bitrix/php_interface/

    

Сверьте вызовы API

  • CBPWorkflowTemplateLoader::setShowInTimelineBeforeUpdate(array &$fields, ?string $templateType, int $id) (26.1500.0) получил обязательный $id. Наследник загрузчика со старой сигнатурой упадёт с фатальной ошибкой.
  • Api\Service\WorkflowTemplateService::saveTemplate() и saveTemplateDraft() (26.1500.0) пропускают только белый список полей и молча отбрасывают TYPE, SYSTEM_CODE, ACTIVE, CREATED_BY и UPDATED_BY.
  • PROPERTY_VALUE в GlobalConstTable и GlobalVarTable (26.1700.0) десериализуется по белому списку: даты и время из BaseType\Value и Main\Type, \DateTime, \DateTimeZone. Объекты других классов станут __PHP_Incomplete_Class.
  • Public\Provider\TemplateAccessProvider::getEntityFilter() (26.1500.0) при опции access_rights_own_templates=Y и праве «свои шаблоны» возвращает ConditionTree под ключом SCOPE_CONDITION_KEY. Его место в Query::where(), в массив filter он не ляжет. По умолчанию опция выключена. Код, готовый к обоим вариантам:
        <?php declare(strict_types=1);

use Bitrix\Bizproc\Public\Provider\TemplateAccessProvider;
use Bitrix\Bizproc\Workflow\Template\Entity\WorkflowTemplateTable;
use Bitrix\Main\Engine\CurrentUser;
use Bitrix\Main\Loader;

Loader::requireModule('bizproc');

$filter = (new TemplateAccessProvider())->getEntityFilter((int)CurrentUser::get()->getId());
$scope = $filter[TemplateAccessProvider::SCOPE_CONDITION_KEY] ?? null;
unset($filter[TemplateAccessProvider::SCOPE_CONDITION_KEY]);

$query = WorkflowTemplateTable::query()
    ->setSelect(['ID', 'NAME'])
    ->setFilter($filter);

if ($scope !== null) {
    $query->where($scope);
}

$templates = $query->fetchAll();

    

Решите, нужен ли новый дизайнер (26.1700.0)

Новый дизайнер БП включён по умолчанию. Опцию designer_v2 заменил флаг Bitrix\Bizproc\Public\Feature\Designer\DesignerV2Flag, а фоновая задача переписывает опцию под его значение. Где дизайнер не включали, он включится, и designer_v2 станет Y. Вернуть старое поведение можно так, синхронизация потом запишет N:

        <?php declare(strict_types=1);

use Bitrix\Bizproc\Public\Feature\Designer\DesignerV2Flag;
use Bitrix\Main\Config\Feature;
use Bitrix\Main\Loader;

Loader::requireModule('bizproc');

Feature::disable(DesignerV2Flag::class);

    

Не подставляйте ID файлов в задания (26.1700.0)

Файловые поля «Запроса дополнительной информации» принимают только ID, который уже стоит в поле, пришёл из загрузчика этого поля или сохранён текущим запросом. Остальные ID молча отбрасываются. Интеграция, которая закрывает задание через bizproc.task.do или REST bizproc.task.complete с ID существующего файла, файл не прикрепит. В REST передавайте содержимое файла.

В карточке задания вместо <input type="file"> теперь виджет загрузки bizproc.task.file-field. Кастомные шаблоны карточки и JS, которые ищут file input, его не найдут.

Проверьте права, роботов и ноды

CBPVirtualDocument::canUserOperateDocumentType() (26.1600.0) для нестатусных процессов на виртуальных документах (bizproc.wizards, инфоблоки type_*) спрашивает права инфоблока. Раньше почти любая операция разрешалась всем, теперь сотрудники без прав на инфоблок потеряют доступ.

Нода нового дизайнера, у которой не нашёлся документ из контекста, пропускается с записью «Действие пропущено: не удалось определить документ» (26.1600.0). Раньше действие, включая удаление, выполнялось над документом процесса.

Автором изменений от роботов теперь пишется сотрудник, сменивший статус, а CBPSetFieldActivity при пустом ModifiedBy пишет запустившего процесс (26.1500.0). У Automation\Engine\Runtime::runDocumentStatus() и onDocumentStatusChanged() появился необязательный ?int $initiatorUserId, наследник со старой сигнатурой несовместим.

Что увидят пользователи

Список шаблонов bizproc.template.processes (26.1600.0) перешёл на фильтр bizproc_template_processes_filter_v2, сохранённые настройки фильтра пропадут. По умолчанию стоит новый пресет «Мои», и страница открывается только со своими шаблонами.

Описания шаблонов в списках запуска и в админке выводятся простым текстом, HTML не рендерится (26.1500.0). Скопированные шаблоны bizproc.wizards.start, bizproc.workflow.start и bizproc.template.processes этого не получат.

Что закрыто

  • 26.1500.0: запуск смарт-скриптов без права на тип документа; XSS в описании шаблона в bizproc.wizards.start; подмена TYPE, SYSTEM_CODE и авторства при сохранении шаблона; поиск хранилища по коду через LIKE, который мог попасть в чужое хранилище; копирование чужого ИИ-агента без права на редактирование.
  • 26.1600.0: удаление процесса в bizproc.workflow.instances без прав администратора; выдача глобальных переменных и констант через bizproc.globalfield.reload без прав; доступ к виртуальным документам и действия над чужим документом при битом контексте ноды.
  • 26.1700.0: файловые поля заданий принимали ID любого файла портала, загрузчик файлов заданий не проверял исполнителя, unserialize глобальных констант ничем не ограничивался.

БД

  • b_bp_workflow_template_change (26.1500.0): колонки AUTHOR_TYPE, AI_TOOL, INITIATOR_USER_ID, REQUEST_SOURCE, CHANGES, CHANGES_SUMMARY и HAS_SNAPSHOT. Агент TemplateChangeCleanupAgent раз в сутки удаляет записи старше 90 дней (template_change_retention_days), записи со снимком версии остаются.
  • 26.1600.0: колонка b_bp_workflow_template_draft.REVISION, таблицы b_bp_workflow_template_lock, b_bp_workflow_template_note и b_bp_workflow_template_note_message. Удаление шаблона чистит его блокировки и заметки.
  • 26.1700.0: таблица фрагментов схемы b_bp_workflow_template_fragment, ORM Workflow\Template\Fragment\Entity\TemplateFragmentTable.

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

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

Подписаться

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

bizproc 26.1800.0 Ломающее Свежее

Bizproc 26.1800.0: ошибка действия обрывает ветку, опции стали feature-флагами

В Bizproc 26.1800.0 действие на `BaseActivity`, вернувшее ошибку, обрывает свою ветку в новом конструкторе, поля «Файл» в хранилищах закрыты для записи, а одиннадцать скрытых опций модуля заменены feature-флагами, и `Option::set()` их больше не включает. Свои действия, запись файлов в хранилища, скр…

2 мин
bizproc 26.1450.0 Рутинное Свежее

bizproc 26.1450.0: установщик подключает модуль до создания ролей

В bizproc 26.1450.0 в установщик модуля добавилась одна строка. Метод `InstallDB()` теперь вызывает `\Bitrix\Main\Loader::includeModule(’bizproc’)` сразу после `RegisterModule()` и только потом `AccessInstaller::install()`, который заводит предустановленные роли доступа. `AccessInstaller::install()`…

1 мин

bizproc 26.1400.0 + bizprocdesigner 26.800.0: новые REST-методы внешнего AI-агента, дочерние действия в CBPActivity, история версий шаблонов

bizproc 26.1400.0 и bizprocdesigner 26.800.0 ставятся одним шагом. Внешнему AI-агенту дизайнера придётся сменить имена трёх методов и формат запросов, потому что его V3-контроллеры перевели с `ArrayResponse` на типизированные запросы и DTO. Свои действия из `/local/activities` стоит проверить на обн…

4 мин
bizproc 26.1300.0 Безопасность

bizproc 26.1300.0 + bizprocdesigner 26.700.0: дизайнер проверяет права на присланный documentType, внешнего AI-агента вернули владельцу его копии

bizprocdesigner 26.700.0 ставится одним шагом с bizproc 26.1300.0 и закрывает экшен, который без проверки прав отдавал категории и стадии любого присланного клиентом типа документа. Внешнего AI-агента на псевдотипе `Workflow`, которого с bizproc 26.1200 подключал только администратор, снова может по…

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

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

на связи

пишет…

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

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

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

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

Войти