«Запретить копирование» в Telegram: что на самом деле защищает новая кнопка

1 марта 2026 года Telegram добавил в личные чаты кнопку «Запретить копирование». Нажал — и собеседник больше не может переслать, скопировать или сохранить ваши сообщения. По крайней мере, так это выглядит для пользователя.

Я разрабатываю сервис для выгрузки переписок и файлов из Telegram, который работает через сессию самого пользователя. Поэтому после мартовского обновления мне пришлось разобраться, что эта кнопка делает, а что нет. Я открыл исходники Telegram Desktop (ветка dev, коммит 3a2a9a3 от 4 ноября 2026) и прошёл весь путь: от флага в API до того, что исчезает в меню.

Короткий ответ: запрет копирования — это флаг, который официальные приложения добросовестно соблюдают. Шифрования или DRM за ним нет. От случайной пересылки он защищает хорошо, от целенаправленного сохранения — нет. Ниже — подробно, с кодом.

Что появилось в марте

В группах и каналах запрет копирования есть с декабря 2021 года: в changelog Telegram Desktop 3.3 от 7 декабря это названо так: авторы контента могут ограничить сохранение медиа и пересылку. Админ ставит галочку — и никто из участников уже не перешлёт пост.

1 марта 2026 года то же самое пришло в личные чаты. Включить запрет может только пользователь с Telegram Premium: профиль собеседника → «⋯» → «Запретить копирование». По словам самого Telegram, после этого собеседник не может пересылать и копировать сообщения, делать снимки экрана и сохранять медиа. В чате появляется служебное сообщение вроде «Анна запретила копирование в этом чате», так что тайно включить его нельзя.

Два флага вместо одного

В группе всё просто: у чата есть один флаг noforwards, и ставит его админ. В личном чате два равноправных участника, поэтому флагов два. В схеме API они лежат в объекте userFull:

userFull#b90c2afd flags:# ... noforwards_my_enabled:flags2.23?true noforwards_peer_enabled:flags2.24?true ...

Первый означает «запрет включил я», второй — «запрет включил собеседник». Клиент складывает их в свои флаги пользователя, а дальше всё сводится к одной функции:

// Telegram/SourceFiles/data/data_user.cppbool UserData::allowsForwarding() const {return !(flags() & Flag::NoForwardsMyEnabled)&& !(flags() & Flag::NoForwardsPeerEnabled);}

Хватает любого из двух флагов, чтобы чат стал «защищённым» для обоих. Вы включили запрет — вы тоже не сможете переслать сообщения собеседника.

Кроме флага на чате, есть флаг noforwards на отдельном сообщении. Им пользуются, например, боты, когда отправляют защищённый контент. Итоговая проверка «можно ли переслать это сообщение» смотрит на оба уровня:

// Telegram/SourceFiles/history/history_item.cppbool HistoryItem::allowsForward() const {return !isService()&& (isRegular() || isEphemeral())&& !forbidsForward() // флаг на сообщении&& history()->peer->allowsForwarding() // флаги на чате&& (!_media || _media->allowsForward());}

Обратите внимание: все эти проверки живут в клиенте. Сервер сообщает приложению «здесь запрет», а уже приложение решает, какие кнопки спрятать.

Что именно выключается

Один и тот же флаг проверяется по всему клиенту: allowsForwarding() на этом коммите встречается в исходниках 28 раз в 21 файле. Вот что из этого видит пользователь Telegram Desktop:

Действие

Где проверяется

Что происходит

Переслать

HistoryItem::allowsForward()

Пункта нет; в меню пишется, кто запретил копирование

Копировать текст

hasCopyRestriction()

Пункта «Копировать» нет

Сохранить фото, видео, файл

hasCopyMediaRestriction(), forbidsSaving()

Нет «Сохранить как…» и скачивания из просмотрщика

Экспорт истории чата

PeerData::canExportChatHistory()

Пункт исчезает из меню чата

Скриншоты

ScreenshotProtection

Зависит от ОС — см. ниже

Про экспорт стоит сказать отдельно. Раньше это был самый простой способ забрать личную переписку целиком: ⋮ → «Экспорт истории чата», и на диске лежит HTML со всеми вложениями. Теперь первой же строкой проверки он отключается:

// Telegram/SourceFiles/data/data_peer.cppbool PeerData::canExportChatHistory() const {if (isRepliesChat() || isVerifyCodes() || !allowsForwarding()) {return false;}...}

Кстати, forbidsSaving() срабатывает не только в защищённых чатах. Точно так же клиент не даёт сохранить исчезающие фото и видео с таймером и платный контент — для него это одна и та же ситуация.

Снять запрет в одиночку нельзя

Отдельно стоит посмотреть, как запрет снимается: здесь схема асимметричная. Включить запрет можно в один клик (если есть Premium), а снять запрет собеседника — только с его согласия. Иначе защита теряла бы смысл: нажал «Разрешить» — и сохраняй что хочешь.

В клиенте это выглядит так (сокращено):

// Telegram/SourceFiles/window/window_peer_menu.cppconst auto willBeRequest = true&& (user->flags() & UserDataFlag::NoForwardsPeerEnabled)&& !peer->session().data().sharingRecentlyDisabledByMe(user);if (willBeRequest) {// «You need {name}'s approval to enable sharing. Send a request?»controller->show(Ui::MakeConfirmBox({ ... }));} else {toggleNoForwards(false);}

Если запрет стоит со стороны собеседника, вместо переключения получается запрос. В чате появляется служебное сообщение «Анна хочет разрешить копирование» со списком того, что включится: пересылка, сохранение фото и видео, копирование сообщений. У второй стороны кнопки «Принять» и «Отклонить», а у самого запроса есть срок жизни: если не ответить, он истечёт.

На уровне API за всё это отвечают один метод и два типа служебных сообщений:

messages.toggleNoForwards#b2081a35 flags:# peer:InputPeer enabled:Bool request_msg_id:flags.0?int = Updates;messageActionNoForwardsToggle#bf7d6572 prev_value:Bool new_value:Bool = MessageAction;messageActionNoForwardsRequest#3e2793ba flags:# expired:flags.0?true prev_value:Bool new_value:Bool = MessageAction;

request_msg_id — это ссылка на сообщение-запрос: и «Принять», и «Отклонить» вызывают этот же метод с id запроса, просто с разным enabled: false при согласии, true при отказе. А флаг expired превращает кнопки в надпись «Срок запроса истёк». Получается небольшой протокол согласия: запрос, ответ и срок действия.

Одна деталь, которую легко пропустить: проверка sharingRecentlyDisabledByMe смотрит, не включали ли вы сами запрет за последние 24 часа с этого устройства. Это локальная подсказка для интерфейса: решает, применить ли изменение сразу или отправить запрос, а последнее слово за сервером.

Скриншоты: честно на macOS, частично на Windows, никак на Linux

Раньше в баг-трекере Telegram на жалобу «в защищённой группе можно делать скриншоты с компьютера» отвечали, что это ожидаемое поведение. Защита запрещала копирование текста, пересылку и сохранение медиа — и всё.

В актуальном коде это уже не так. Появился класс Core::ScreenshotProtection, а защита опирается на механизмы операционной системы, которые исключают окно из захвата экрана:

// platform/mac/specific_mac.mmnsWindow.sharingType = enabled? NSWindowSharingNone: NSWindowSharingReadOnly;// platform/win/specific_win.cppbool AmbientScreenshotProtectionSupported() {// Display affinity hides the window from the viewer, not just captures.return false;}...SetWindowDisplayAffinity(hwnd, WDA_EXCLUDEFROMCAPTURE);// platform/linux/specific_linux.hinline bool AmbientScreenshotProtectionSupported() {return false;}

Разница между системами получается заметной:

Система

Окно с защищённым чатом

Просмотр фото и видео из него

macOS

Исключено из захвата экрана

Исключено

Windows

Не защищено

Исключено

Linux

Не защищено

Не защищено

Почему на Windows защищён только просмотрщик, подсказывает комментарий в коде: защита через SetWindowDisplayAffinity прячет окно не только от скриншотов. Если включить её на главном окне, то при демонстрации экрана в Zoom или Discord мессенджер целиком исчезнет из трансляции, стоит только открыть защищённый чат. Поэтому на Windows её включают только для окна просмотра фото и видео. На Linux функции защиты — просто заглушки.

И одно общее для всех систем: это защита от программного захвата экрана. Камеру телефона, наведённую на монитор, она не остановит.

Главное: правило соблюдает клиент, а не сервер

Все проверки выше объединяет одно: они выполняются на стороне приложения. Сервер доставляет сообщения и файлы на все авторизованные устройства аккаунта и вместе с ними передаёт флаг noforwards. Дальше всё зависит от того, кто этот флаг читает.

Официальные приложения его соблюдают. Но если в клиенте есть ошибка, защита протекает. Хороший пример — строчка из changelog Telegram Desktop 7.3.1 от 9 октября 2026 года: «Fix copy-restricted media reaching Downloads». Защищённые файлы в каких-то сценариях оказывались в папке загрузок, пока это не починили.

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

Если свести всё вместе:

Защищает

Не защищает

От случайной пересылки в другой чат

От фото экрана на телефон

От «скинь мне всю переписку» через экспорт в Desktop

От скриншотов окна чата на Windows и Linux

От быстрых скриншотов в мобильных приложениях и на macOS

От сторонних клиентов в том же аккаунте

От сохранения фото и видео в галерею одним нажатием

От того, что собеседник успел сохранить до включения запрета

По сути, запрет копирования ставит лишнюю преграду. Он делает сохранение неудобным и заметным, но не невозможным. Для большинства ситуаций этого хватает: мало кто станет фотографировать экран, чтобы переслать чужую фотку в общий чат.

Что из этого следует на практике

Если вы включаете запрет:

  • Считайте его вежливой просьбой «не распространяй», закреплённой интерфейсом. От человека, который хочет сохранить переписку, он не спасёт.

  • Запрет не действует задним числом. Всё, что собеседник уже переслал или выгрузил, остаётся у него.

  • Для действительно чувствительных вещей есть секретные чаты и таймер самоуничтожения. Но и они не защитят от камеры в руках собеседника. Лучшая защита — не отправлять то, чем не готовы делиться.

Если вы получатель:

  • Важные договорённости сохраняйте заранее: сейчас экспорт в Telegram Desktop работает, а после включения запрета пункт исчезнет из меню.

  • Если переписка нужна для дела — попросите снять запрет. Для этого в Telegram есть штатный запрос с кнопками «Принять» и «Отклонить».

  • И очевидное: запрет — это явно выраженное желание собеседника. Хранить свою переписку для себя — одно, распространять чужие сообщения — совсем другое.

Итог

«Запретить копирование» в личных чатах сделан аккуратно: два флага вместо одного, служебные сообщения, чтобы никто не включил его тайком, протокол согласия для снятия и защита от захвата экрана там, где её даёт ОС. Но по своей природе это клиентская договорённость: она работает ровно настолько, насколько её соблюдает приложение на другой стороне.

Если вам попадались другие интересные места в исходниках Telegram, связанные с приватностью, — пишите в комментариях, разберём.

P.S. Тот самый сервис из вступления — SpyGrabs. Если интересно, как работа через сессию пользователя устроена с точки зрения безопасности, — спрашивайте в комментариях, расскажу.

Источники:

  • Исходники Telegram Desktop, коммит 3a2a9a3: data_user.cpp, data_peer.cpp, history_item.cpp, window_peer_menu.cpp, api_suggest_post.cpp, core_screenshot_protection.cpp, specific_mac.mm, specific_win.cpp, specific_linux.h

  • Changelog Telegram Desktop — версии 3.3, 6.6 и 7.3.1

  • Схема API, api.tl

  • Блог Telegram, 1 марта 2026: запрет на копирование в чатах

  • Баг-трекер Telegram: обсуждение скриншотов в защищённых группах

Источник: habr.com

0 0 голоса
Рейтинг новости
1
0
Подписаться
Уведомить о
0 комментариев