sign 26.700.0 Безопасность

Sign 26.700.0: чужие группы подписантов закрыли проверкой доступа, подписания можно аннулировать

4 мин чтения

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

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

Модуль «Подписание документов» (sign) версии 26.700.0 вышел в коробочный Битрикс24 17 сентября 2026 года, так указано в официальном канале «Битрикс24 changelog». В релизе закрыли утечку состава чужих групп подписантов и документов, добавили проверки доступа к повторной отправке и выпустили аннулирование подписаний и массовые действия в «Моих документах». После обновления стоит прогнать свой интерфейс настройки подписантов, скрипты повторной отправки и отчёты по юридическому журналу.

Чужую группу подписантов больше не прочитать

Источником подписантов может быть группа подписантов или другой документ. В комментарии к новому Bitrix\Sign\Access\Service\SelectorSourceAccessService сказано, что без проверки доступа к источнику любой пользователь мог прочитать состав чужой группы или документа, передав их ID.

Сервис проверяет выбранные группы и документы методами checkSelectorEntities() и checkEntityCollection(), порциями по 300. Группы проверяются пачкой через новый SignersList\AccessService::getAccessibleLists(). В том же AccessService кеш контроллера доступа теперь хранится по ID пользователя. Комментарий объясняет это тем, что текущий пользователь может смениться внутри одного процесса.

Ещё две проверки появились на уровне отдельного документа. Старый контроллер Controller\Internal\Document::resendFileAction() теперь требует права на чтение или редактирование документа и без него возвращает ACCESS_DENIED. Повторная отправка в Controllers\V1\Document\Send проверяет каждый документ из запроса через checkByItem().

Четыре экшена отвечают 401 на чужой источник подписантов

SelectorSourceAccessService приходит автовайрингом в четыре действия контроллеров. Параметр вставлен перед bool $excludeRejected = true:

  • Controllers\V1\B2e\Document\Template::setupSignersAction();
  • Controllers\V1\B2e\Signers::addSignersToListAction();
  • Controllers\V1\Document\Member::getUniqSignersCountAction();
  • Controllers\V1\Document\Member::setupB2ePartiesAction().

Для AJAX-вызовов параметр прозрачен. Если среди подписантов есть группа или документ, к которым у пользователя нет доступа, запрос отклоняется с 401. Свой интерфейс, который собирает подписантов из групп и документов, научите показывать такой отказ пользователю. При прямых вызовах этих методов из PHP и в наследниках контроллеров сверьте сигнатуры, потому что сервис встал перед $excludeRejected.

Повторная отправка молча пропускает недоступные документы

Для повторной отправки сообщения Controllers\V1\Document\Send раньше требовал общее право ACTION_DOCUMENT_EDIT. Теперь хватает ACTION_DOCUMENT_READ или ACTION_DOCUMENT_EDIT, но каждый документ из запроса дополнительно проверяется через checkByItem(). Документы без доступа отбрасываются молча.

Пользователь с правом только на чтение теперь может повторно отправить сообщение по доступному ему документу. Скрипт, который шлёт пачку участников (memberIds), ошибки по недоступным не получит, так что ответ без ошибок больше не означает, что ушли все.

Копия группы подписантов теряет уволенных и экстранет

Operation\Signers\CopyList при копировании группы молча не переносит уволенных и экстранет-пользователей. Если после копирования вы сверяете число участников с исходной группой, цифры могут разойтись. Конструктор CopyList получил необязательный параметр в конце, прямые вызовы от этого не сломаются.

Юридический журнал научился не подставлять текущего пользователя

Если инициатор стопа не найден, Service\Sign\LegalLogService подставляет в запись текущего пользователя. Теперь запись о стопе можно сохранить без автора. В ядре так делает только новый Operation\SigningStopBatch, который останавливает документы при массовом отклонении (reject) в «Моих документах». Если сервис подписи отвечает already_done, документ остановили раньше, и запись о стопе остаётся без пользователя. Колбэк сервиса подписи (Callback\Handler) и обычный SigningStop флаг не передают и, если инициатор не найден, по-прежнему подставляют текущего пользователя.

Для этого добавили необязательные параметры:

  • register(..., bool $substituteCurrentUser = true);
  • registerDocumentStop(..., bool $initiatorIsUnknown = false);
  • registerDocumentChangedStatus(..., bool $initiatorIsUnknown = false);
  • Operation\ChangeDocumentStatus::__construct(..., bool $initiatorIsUnknown = false).

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

        <?php declare(strict_types=1);

use Bitrix\Main\Loader;
use Bitrix\Sign\Service\Container;

Loader::requireModule('sign');

$container = Container::instance();
$document = $container->getDocumentRepository()->getByUid($documentUid);

if ($document !== null) {
    // документ остановили не в портале, текущий пользователь тут ни при чём
    $container->getLegalLogService()->registerDocumentStop($document, initiatorIsUnknown: true);
}

    

Новое: аннулирование подписаний

Подписание теперь можно аннулировать. Это обратимая отметка на участнике, поэтому у всех действий есть флаг bool $annul:

  • Controllers\V1\Document\Member::annulAction(string $uid, bool $annul) для одного участника;
  • Controllers\V1\Document\Member::annulBatchAction(array $uids, bool $annul) для нескольких;
  • Controllers\V1\Document::annulByDocumentAction(string $uid, bool $annul) по документу.

Внутри работают операции Operation\AnnulDocument и Operation\AnnulDocumentMembers, а также Service\B2e\AnnulmentTargetService, Item\B2e\AnnulmentTarget и Result\Repository\Member\AnnulmentSwitchResult. HR-бот получил сообщения Messages\Failure\DocumentAnnulled и AnnulmentCanceled, в HrBotMessageService добавлены handleMemberAnnulled(), handleMembersAnnulled() и scheduleMembersAnnulled(). В гриде аннулированные подписания помечает AnnulledLabelTemplate, JS лежит в расширении sign.v2.grid.b2e.annul, а в FeatureResolver появилась фича kedoDocumentAnnul.

Под аннулирование завели право SignPermissionDictionary::SIGN_DOCUMENT_ANNUL = 27 и действие ACTION_DOCUMENT_ANNUL, владельца документа проверяет Access\DocumentAnnulPermission. По умолчанию роль сотрудника получает NONE, роль руководителя SUBDEPARTMENT. Права раскладывают AccessInstaller::installMissingDocumentAnnulPermission() и UpdateDefaultPermissionsAgent.

Отметка хранится в b_sign_member в колонках ANNULLED, ANNULLED_BY_ID и DATE_ANNULLED. Если ваши отчёты считают подписанных участников, учитывайте ANNULLED. Список аннулированных по документу можно достать так:

        <?php declare(strict_types=1);

use Bitrix\Main\Loader;
use Bitrix\Sign\Internal\MemberTable;

Loader::requireModule('sign');

$annulled = MemberTable::getList([
    'select' => ['ID', 'ANNULLED_BY_ID', 'DATE_ANNULLED'],
    'filter' => ['=DOCUMENT_ID' => $documentId, '=ANNULLED' => true],
])->fetchAll();

    

Новое: массовые действия в «Моих документах»

Массовые действия принимает Controllers\V1\B2e\Document\Member::processBulkAction(array $data). Запрос идёт методом POST, тело можно прислать как JSON, urlencoded или multipart. Действий в enum Type\MyDocumentsGrid\BulkAction два, approve и reject, а выполняет их Operation\B2e\MyDocuments\ProcessBulkAction. Для пакетных запросов к сервису подписи добавлены ReviewBatchRequest и RefuseBatchRequest из Item\Api\Mobile\Signing, Item\Api\Document\Signing\StopBatchRequest, операция Operation\SigningStopBatch, трейт Trait\Api\BatchRequestTrait и типы Type\Api\BatchItemStatus и TransportErrorCode. На фронтенде это расширение sign.v2.grid.b2e.my-documents.bulk-action-process.

Выключить функцию можно опцией ~b2e_bulk_action_available, её читает Config\Storage::isB2eBulkActionAvailable(). По умолчанию опция равна 'Y'.

        <?php declare(strict_types=1);

use Bitrix\Main\Config\Option;
use Bitrix\Main\Loader;
use Bitrix\Sign\Config\Storage;

Loader::requireModule('sign');

Option::set('sign', '~b2e_bulk_action_available', 'N');

$enabled = Storage::instance()->isB2eBulkActionAvailable(); // false

    

Новое: подписанный файл во встроенном просмотрщике

Ссылку на подписанный файл для встроенного просмотрщика отдаёт Controllers\V1\Document\B2eSignedFile::getFileUrlForUiViewerAction(string $sign, string $url). Фильтров CSRF и ContentType у действия нет, проверяются подпись URL и его состав. Рядом добавлены операция Operation\GetSignedB2eFileUrlForUiViewer и сервис Service\B2e\MyDocumentsGrid\SignedFileService, а для пакетной выдачи ссылок GetSignedB2eFileUrl::createByPreloadedFile().

В комментарии в B2eSignedFile сказано, что проверку сейфа при скачивании убрали в #254143, потому что она не считала подписанта владельцем документа. Сейчас файл защищает только подпись URL.

Облегчённый Госключ ограничили по тарифу, коробку это не задело

На демо- и бесплатном облачном тарифе goskey-lite не объявляется в supportedProviders и отклоняется при подключении (Operation\GetRegisteredCompanies, Controllers\V1\Integration\Crm\B2eCompany). Проверку делают новые Integration\Bitrix24\B2eTariff::isGoskeyLiteRestrictedInCurrentTariff() и getGoskeyLiteAccessError(). Без модуля bitrix24 первый метод всегда возвращает false, так что в коробке облегчённый Госключ тарифом не ограничен.

Для работы с провайдерами добавили ProviderCode::getGoskeyProviders() и isGoskeyProvider(). В getGoskeyProviders() отдельно помечено, что аналитика нарочно различает GOS_KEY и GOS_KEY_LITE. Провайдер появился в 26.450.0, промо к нему в 26.600.0, тарифное ограничение пришло в этом релизе.

БД

Изменение схемы есть только в install/migrations/tables.php, декларативном описании таблиц модуля. В b_sign_member добавлены ANNULLED tinyint NOT NULL DEFAULT 0, ANNULLED_BY_ID int и DATE_ANNULLED datetime, в Internal\MemberTable появились соответствующие ORM-поля. Как колонки доезжают до уже установленных порталов, из диффа не видно.

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

  • Engine\Controller::addAccessDeniedError() отдаёт единый ответ 401 с фразой SIGN_ENGINE_CONTROLLER_ERROR_ACCESS_DENIED. Controllers\V1\B2e\Member его намеренно не использует. Эндпоинт аватаров анонимный, его вызывает сервис подписи, и он должен оставаться на HTTP 200.
  • Для ошибки подготовки документа завели коды B2eErrorCode::DOCUMENT_PREPARATION_FAILED и DOCUMENT_PREPARATION_UNAVAILABLE, проверку isDocumentPreparationFailure(), сообщение Messages\Failure\DocumentPreparationFailed и HrBotMessageService::notifyDocumentPreparationFailed(). Для ответственного такая ошибка пишется в юридический журнал.
  • Остальные изменения сигнатур тоже добавляют необязательные параметры в конец. Это Item\Member (annulled, annulledById, dateAnnulled), Item\MyDocumentsGrid\Document (isAnnulled, canAnnul), MemberRepository::listByIds() и listByDocumentIdListAndRoles() (bool $loadEntityNames = true), ChangeMemberStatus (?LoggerInterface $logger) и конструкторы Ui\MyDocumentsGrid\*.
  • Из Engine\ActionFilter\AccessCheck вычистили ссылки на тикеты «jabber #249372» и «jabber #249595», которые появились там в 26.500.0, комментарии переписаны без номеров. В других местах внутренние ссылки остались или появились новые. В tables.php упомянут документ требований «PRD-kedo-annulment-signing-chat-2026-07-10», в B2eSignedFile номер #254143.
  • VERSION_DATE у 26.700.0 указан 30 июля 2026.
  • Deprecated в релизе нет.

Что делать

  • Прогоните свой интерфейс настройки подписантов под пользователем, у которого нет доступа к части групп и документов, и проверьте, как он показывает ответ 401.
  • Если скрипт повторно отправляет сообщения пачкой участников, не считайте ответ без ошибок подтверждением, что ушли все.
  • Предупредите тех, кто строит отчёты по юридическому журналу, что запись о стопе после массового отклонения в «Моих документах» может быть без пользователя.
  • Решите, каким ролям нужно право SIGN_DOCUMENT_ANNUL, и добавьте ANNULLED в свои отчёты по подписанным участникам.
  • После обновления проверьте, что в b_sign_member на вашей базе есть колонки ANNULLED, ANNULLED_BY_ID и DATE_ANNULLED.

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

sign 26.600.0 Безопасность Свежее

Sign 26.450.0–26.600.0: IDOR в AccessCheck, установщик на миграциях и папки в сейфе компании

Версии 26.450.0, 26.500.0 и 26.600.0 модуля sign («Подписание документов») вышли в коробочный Битрикс24 одним днём, 11 сентября 2026 года, так указано в официальном канале «Битрикс24 changelog». Срочнее всего 26.500.0, которая закрывает IDOR в фильтре `AccessCheck` и заодно переводит установщик на м...

5 мин
voximplant 26.700.0 Ломающее Свежее

Voximplant 26.700.0: оценку качества связи убрали, у notifyAdmins() появился тип

Модуль телефонии voximplant 26.700.0 вышел в коробочный Битрикс24 11 сентября 2026 года, по данным официального канала «Битрикс24 changelog». Из карточки звонка убрали оценку качества связи вместе с её JS-событиями, у `Im::notifyAdmins()` появился тип параметра, а публичные константы `SipStatusInfor...

3 мин
ui 26.687.0 Рутинное Свежее

UI 26.687.0: триал VibePlus в облаке и дизайн чипа TintedBitrixGpt

`Bitrix\UI\Controller\InfoHelper` при активации демо сначала спрашивает у модуля bitrix24, включён ли старт VibePlus, и если да, запускает триал VibePlus вместо обычного демо тарифа. Ветка срабатывает только при подключённом модуле bitrix24 и определённой константе `BX24_HOST_NAME`. В `ui.system.chi...

1 мин
ui 26.675.0 Ломающее Свежее

UI 26.675.0: ui.actionpanel переехал в бандл, а rich_text по-новому обходится с квадратными скобками

Модуль ui 26.675.0 собран 26 августа 2026. Из PHP поменялись `Converter` и `Whitelist` в `Bitrix\UI\Format\BBCode`, и пользовательские поля типа `rich_text` теперь иначе сохраняют и индексируют текст с квадратными скобками. На фронтенде старую панель групповых действий `ui.actionpanel` перевели на б...

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

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

на связи

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

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

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

Войти